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.
| Record | MyCRM resource and example ID | Purpose |
|---|---|---|
| Integration | integrations / 42 | Names the external system: Partner Portal |
| Contact | contacts / 1001 | The person in MyCRM |
| Contact reference | contact-external-references / 7001 | Links that contact to portal customer CUST-0042, through integration 42 |
| Deal | deals / 3001 | The opportunity in MyCRM |
| Deal reference | deal-external-references / 8001 | Links 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.
2. Link an existing contact and deal
Link your customer ID to a contact
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.
Link your opportunity ID to a deal
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 point | Read the related reference resources |
|---|---|
Contact 1001 | GET /jsonapi/contacts/1001/externalReferences |
Deal 3001 | GET /jsonapi/deals/3001/externalReferences |
Integration 42, contact mappings | GET /jsonapi/integrations/42/contactExternalReferences |
Integration 42, deal mappings | GET /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.
| Field | Meaning |
|---|---|
externalReference | Your external opportunity or enquiry ID, up to 255 characters. It is stored on the resulting deal reference. |
externalIntegration | The integration’s name, up to 100 characters — for example, Partner Portal, not its numeric MyCRM ID. Required when supplying an external reference. |
externalIntegrationAllowCreate | Whether 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 state | externalIntegrationAllowCreate: true | externalIntegrationAllowCreate: false |
|---|---|---|
| Active integration with that name exists | Reuse it | Reuse it |
| No matching integration exists | Create it, then attach the reference | Reject with 400; the integration does not exist |
| Matching integration is inactive | Reactivate it, then attach the reference | Reject 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.
| Symptom | What to check |
|---|---|
400 saying the external integration does not exist | With allow-create set to false, check the name, active state and receiving adviser’s organisation. |
| A required or inaccessible relationship | Supply the correct type and MyCRM ID for both relationships; confirm the integration’s organisation and access to the contact or deal. |
| An update rejects relationships | PATCH only externalReference; omit relationships entirely. |
| A second reference cannot be created for the same record and integration | Find the existing reference and update it using its own ID. |
| Missing references or multiple matches | Check application access, organisation, integration ID, external value and all result pages. Do not silently select a match or create a replacement. |
401 or 403 | Check 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.