Skip to main content

External integrations and references

External references let your application recognise the same customer or opportunity in MyCRM and another system. For example, your partner portal might know a customer as CUST-0042, while MyCRM knows that person as contact 1001. A reference records that connection so you can find the right record again without matching names or email addresses.

This walkthrough uses a fictional Partner Portal integration. It covers setting up the integration, linking existing contacts and deals, finding those records later, and supplying references when creating a lead.

How the records fit together​

An integration is an organisation’s named external system. An external reference is a separate record connecting that integration to one contact or deal.

RecordMyCRM resource and example IDPurpose
Integrationintegrations / 42Names the external system: Partner Portal
Contactcontacts / 1001The person in MyCRM
Contact referencecontact-external-references / 7001Links that contact to portal customer CUST-0042, through integration 42
Dealdeals / 3001The opportunity in MyCRM
Deal referencedeal-external-references / 8001Links that deal to portal opportunity OPP-2026-0042, through integration 42

Keep the identifiers separate. 7001 is the MyCRM ID of a mapping; 1001 is the contact it points to; CUST-0042 is the external value stored in it. Use the mapping ID when updating or deleting the reference.

An integration record describes these mappings. Creating one does not issue OAuth credentials, grant access, establish a webhook subscription or start synchronising data. Your application performs the actual connection.

Before you start​

Use an access token, the API base URL and the assigned adviser contact ID supplied for your application. Request permission for the operations you need on integrations, contact references and deal references. Reading the related contacts or deals and creating leads require their own applicable permissions. Collection search and read-by-ID are also separate capabilities; see scopes.

Integrations belong to an organisation. Creation uses the organisation of the adviser resolved from UserId; reference creation requires an integration in that organisation and access to the contact or deal being linked. Your application’s access agreement still applies. A leads-only credential does not automatically grant access to the integration and reference collections.

All IDs below are fictional. Replace them with IDs returned in your environment. JSON:API resource IDs are strings in the request body. The HTTP examples show the complete headers and body; the curl examples assume API_BASE_URL, ACCESS_TOKEN and ADVISER_CONTACT_ID are set locally.

1. Find or create your integration​

Start by checking whether the external system already has an integration record:

curl --get "$API_BASE_URL/jsonapi/integrations" \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header "UserId: $ADVISER_CONTACT_ID" \
--header 'Accept: application/vnd.api+json' \
--data-urlencode "filter=equals(name,'Partner Portal')"

Check the returned records and follow pagination links if present. Reuse the appropriate integration for the organisation; do not create one for every customer or request. Keep one agreed name for each external system. If several records have that name, resolve the ambiguity before proceeding.

If it does not exist and you have permission to create it:

POST {API_BASE_URL}/jsonapi/integrations
Authorization: Bearer {ACCESS_TOKEN}
UserId: {ADVISER_CONTACT_ID}
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

{
"data": {
"type": "integrations",
"attributes": {
"name": "Partner Portal",
"description": "Customer and opportunity IDs from our partner portal"
}
}
}

A successful create returns 201 Created. Save its data.id; this walkthrough uses 42. The name is required and allows up to 100 characters; the optional description allows up to 300. Organisation, creation time and update time are set by MyCRM, so do not supply them.

The integration’s contactExternalReferences and dealExternalReferences relationships are for reading its mappings. Do not send those lists to create or assign mappings on the integration itself; use the dedicated reference endpoints in the next step.

Use Search integrations, Create an integration and Read an integration for the full contract.

Suppose portal customer CUST-0042 corresponds to MyCRM contact 1001:

POST {API_BASE_URL}/jsonapi/contact-external-references
Authorization: Bearer {ACCESS_TOKEN}
UserId: {ADVISER_CONTACT_ID}
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

{
"data": {
"type": "contact-external-references",
"attributes": {
"externalReference": "CUST-0042"
},
"relationships": {
"integration": {
"data": {
"type": "integrations",
"id": "42"
}
},
"contact": {
"data": {
"type": "contacts",
"id": "1001"
}
}
}
}
}

Save the returned reference’s data.id — 7001 in this walkthrough. This creates the mapping only; the contact must already exist. Both integration and contact relationships are required, and externalReference is a required string of up to 255 characters.

Suppose portal opportunity OPP-2026-0042 corresponds to MyCRM deal 3001:

POST {API_BASE_URL}/jsonapi/deal-external-references
Authorization: Bearer {ACCESS_TOKEN}
UserId: {ADVISER_CONTACT_ID}
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

{
"data": {
"type": "deal-external-references",
"attributes": {
"externalReference": "OPP-2026-0042"
},
"relationships": {
"integration": {
"data": {
"type": "integrations",
"id": "42"
}
},
"deal": {
"data": {
"type": "deals",
"id": "3001"
}
}
}
}
}

Save this reference’s data.id separately — 8001 here. Both integration and deal relationships are required, with the same 255-character limit on externalReference.

The two references are independent. Linking a deal does not automatically create references for its contacts, and linking a contact does not create a deal reference. Use relationships.integration.data.id in these requests; the name-based externalIntegration fields described below belong to lead creation.

Each contact or deal can have one reference per integration. The same record can have references for several different integrations. To change the external value for an existing pair, update its reference instead of creating another one.

See Create a contact reference and Create a deal reference.

3. Find a MyCRM record from an external ID​

Search using both the integration ID and the external value. Searching only by external value can mix results from different systems.

curl --get "$API_BASE_URL/jsonapi/contact-external-references" \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header "UserId: $ADVISER_CONTACT_ID" \
--header 'Accept: application/vnd.api+json' \
--data-urlencode "filter=and(equals(integration.id,'42'),equals(externalReference,'CUST-0042'))"

For a deal, query the deal reference collection:

curl --get "$API_BASE_URL/jsonapi/deal-external-references" \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header "UserId: $ADVISER_CONTACT_ID" \
--header 'Accept: application/vnd.api+json' \
--data-urlencode "filter=and(equals(integration.id,'42'),equals(externalReference,'OPP-2026-0042'))"

An illustrative excerpt of that deal-reference response is:

{
"data": [
{
"type": "deal-external-references",
"id": "8001",
"attributes": { "externalReference": "OPP-2026-0042" },
"relationships": {
"integration": { "data": { "type": "integrations", "id": "42" } },
"deal": { "data": { "type": "deals", "id": "3001" } }
}
}
]
}

Read relationships.deal.data.id to obtain 3001, then use Read a deal. For contact references, read relationships.contact.data.id, then use Read a contact.

To retrieve related objects alongside the mappings, add include=deal,integration or include=contact,integration. Their resource objects appear in included; match them by type and id. See reading related resources for the JSON:API shape.

An external value is not a uniqueness guarantee. The one-reference rule applies to the integration and MyCRM record pair, not the external value across all records. Handle zero, one or multiple matches, follow pagination, and resolve multiple matches rather than choosing the first. An empty result can also reflect access or an inactive integration; it is not by itself proof that no record was ever created.

For values supplied dynamically, escape filter literals before URL encoding; --data-urlencode handles URL encoding but does not escape an apostrophe inside a filter value. Follow the filter construction guide.

Start from the MyCRM record when you already know its ID​

Starting pointRead the related reference resources
Contact 1001GET /jsonapi/contacts/1001/externalReferences
Deal 3001GET /jsonapi/deals/3001/externalReferences
Integration 42, contact mappingsGET /jsonapi/integrations/42/contactExternalReferences
Integration 42, deal mappingsGET /jsonapi/integrations/42/dealExternalReferences

The corresponding /relationships/... URLs return relationship linkage. To search and page through mappings with filters, use the top-level reference collections shown above. Related reads and includes still depend on access to the relevant resources.

4. Attach a reference while creating a lead​

The lead endpoints offer a shortcut: supply the external opportunity ID and integration name in the lead’s attributes, and MyCRM creates the deal reference as part of creating the lead.

FieldMeaning
externalReferenceYour external opportunity or enquiry ID, up to 255 characters. It is stored on the resulting deal reference.
externalIntegrationThe integration’s name, up to 100 characters — for example, Partner Portal, not its numeric MyCRM ID. Required when supplying an external reference.
externalIntegrationAllowCreateWhether MyCRM may create a missing integration or reactivate an inactive one. Defaults to true in the current implementation; set it explicitly to make your choice clear.

Supply the external reference and integration name together. Without an externalReference, the shortcut does not create a mapping or provision an integration, even if the name and allow-create flag are supplied. To register a system without creating a lead, use POST /jsonapi/integrations.

Simple lead example​

POST {API_BASE_URL}/jsonapi/leads
Authorization: Bearer {ACCESS_TOKEN}
UserId: {ADVISER_CONTACT_ID}
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

{
"data": {
"type": "leads",
"attributes": {
"firstName": "Alex",
"lastName": "Morgan",
"email": "alex@example.com",
"mobile": "+61400000000",
"externalReference": "OPP-2026-0043",
"externalIntegration": "Partner Portal",
"externalIntegrationAllowCreate": true
}
}
}

MyCRM looks for the integration name in the receiving adviser’s organisation, matching without regard to letter case. It then links the supplied external reference to the resulting deal. Keep the spelling and spacing consistent with the agreed integration name.

Integration stateexternalIntegrationAllowCreate: trueexternalIntegrationAllowCreate: false
Active integration with that name existsReuse itReuse it
No matching integration existsCreate it, then attach the referenceReject with 400; the integration does not exist
Matching integration is inactiveReactivate it, then attach the referenceReject with 400; the integration is not available

Use false when you have provisioned the integration in advance and want an unexpected name to be an error. Use true when creating or reactivating an integration during lead submission is intended. The flag does not permit access outside your organisation or create an OAuth client.

A successful lead response uses the resulting deal’s identifier as the lead resource ID. Keep its resource type as leads when reading through the leads endpoint; use deals when linking a deal reference. The reference record has a separate ID. With appropriate access, retrieve it through GET /jsonapi/deals/{id}/externalReferences or search by integration and external value.

The three input fields are write-only on the lead resource; they are not echoed as readable lead attributes. Creating the lead this way does not add a contact reference. If you also need a customer mapping, identify the permitted contact and create it separately through the contact-reference endpoint.

Structured lead example​

The same three fields belong at data.attributes on a structured lead, alongside the contacts array. They apply to the resulting deal, not to each contact in the array. This is an alternative to the simple lead request above; do not submit both for the same enquiry.

POST {API_BASE_URL}/jsonapi/structured-leads
Authorization: Bearer {ACCESS_TOKEN}
UserId: {ADVISER_CONTACT_ID}
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

{
"data": {
"type": "structured-leads",
"attributes": {
"dealName": "Alex Morgan enquiry",
"contacts": [
{
"firstName": "Alex",
"lastName": "Morgan",
"email": "alex@example.com",
"mobile": "+61400000000",
"isPrimary": true
}
],
"externalReference": "OPP-2026-0043",
"externalIntegration": "Partner Portal",
"externalIntegrationAllowCreate": false
}
}
}

This example uses false because step 1 has already established the active integration. See Create a lead and Create a structured lead for all supported fields and validation.

5. Update or remove a mapping​

PATCH the reference record, using its ID in both the URL and data.id. Send the attributes you want to change:

PATCH {API_BASE_URL}/jsonapi/contact-external-references/7001
Authorization: Bearer {ACCESS_TOKEN}
UserId: {ADVISER_CONTACT_ID}
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

{
"data": {
"type": "contact-external-references",
"id": "7001",
"attributes": {
"externalReference": "CUST-0042A"
}
}
}

For the deal reference:

PATCH {API_BASE_URL}/jsonapi/deal-external-references/8001
Authorization: Bearer {ACCESS_TOKEN}
UserId: {ADVISER_CONTACT_ID}
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

{
"data": {
"type": "deal-external-references",
"id": "8001",
"attributes": {
"externalReference": "OPP-2026-0042A"
}
}
}

The integration, contact and deal relationships cannot be reassigned by PATCH, even when their existing IDs are sent unchanged. Leave them out. To correct a mapping to the wrong record or integration, remove the incorrect reference and create a replacement with the correct relationships. Coordinate those separate requests in your application; they are not an atomic replacement.

To remove only a mapping:

DELETE {API_BASE_URL}/jsonapi/contact-external-references/7001
Authorization: Bearer {ACCESS_TOKEN}
UserId: {ADVISER_CONTACT_ID}
Accept: application/vnd.api+json
DELETE {API_BASE_URL}/jsonapi/deal-external-references/8001
Authorization: Bearer {ACCESS_TOKEN}
UserId: {ADVISER_CONTACT_ID}
Accept: application/vnd.api+json

These delete the reference records, not the associated contact, deal or integration. Keep the reference ID so you do not accidentally substitute the contact or deal ID.

See Update a contact reference, Update a deal reference, Delete a contact reference and Delete a deal reference.

Maintain the integration itself​

Use Update an integration to change its name or description. For example:

PATCH {API_BASE_URL}/jsonapi/integrations/42
Authorization: Bearer {ACCESS_TOKEN}
UserId: {ADVISER_CONTACT_ID}
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json

{
"data": {
"type": "integrations",
"id": "42",
"attributes": {
"description": "Customer and opportunity IDs for the partner portal connection"
}
}
}

Existing mappings retain their relationship to the integration’s ID if you rename it. Update applications that still submit its old name through externalIntegration: with automatic creation enabled, an old name can create a different integration and split your mappings.

Retiring an integration

Delete an integration

deactivates it, and inactive integrations are excluded from normal integration reads. This does not delete the underlying contacts or deals, remove OAuth credentials, or stop your application.

DELETE {API_BASE_URL}/jsonapi/integrations/42
Authorization: Bearer {ACCESS_TOKEN}
UserId: {ADVISER_CONTACT_ID}
Accept: application/vnd.api+json

Stop or reconfigure lead submissions before retiring it: a later lead using the same name with externalIntegrationAllowCreate: true can reactivate it. Use the reference DELETE endpoints when your intention is to remove individual mappings.

Keep retries and reconciliation safe​

External references help you find records; they are not idempotency keys. Repeating a lead POST with the same external value can create another deal. The allow-create flag controls the integration record, not whether a lead may be created.

Before a new submission, check your own saved mapping and, where permitted, query MyCRM for the integration and external value. After success, persist the returned IDs. If a request times out or its outcome is unclear, reconcile before retrying. A lookup followed by a create is still vulnerable to concurrent requests; coordinate work for the same external record in your application. With leads-only access, arrange an appropriate reconciliation process rather than assuming the reference search endpoints will be available.

SymptomWhat to check
400 saying the external integration does not existWith allow-create set to false, check the name, active state and receiving adviser’s organisation.
A required or inaccessible relationshipSupply the correct type and MyCRM ID for both relationships; confirm the integration’s organisation and access to the contact or deal.
An update rejects relationshipsPATCH only externalReference; omit relationships entirely.
A second reference cannot be created for the same record and integrationFind the existing reference and update it using its own ID.
Missing references or multiple matchesCheck application access, organisation, integration ID, external value and all result pages. Do not silently select a match or create a replacement.
401 or 403Check token expiry, requested scopes and permitted UserId context. An integration record is not an access grant.

Continue with synchronisation and retries and JSON:API writes.