Skip to content
Esc
↑↓navigate↵open⌘Jpreview

Link external records to people and companies

Idempotently link external platform records (e.g. Stripe customers) to Modem people and companies.

Each person / company block states the facts the platform knows about that side of the record — not an assertion of how to resolve it. Modem owns all matching.

Person — matched by platform identity first, then by exact email. A bare email matches an existing person but never creates one (it may be a shared inbox like billing@); creation requires displayName.

Company — matched by the first hit, in trust order:

  1. an existing platform identity link for this block
  2. the resolved person’s current company
  3. stated domains, then the domain derived from person.email (free-mail domains such as gmail.com carry no signal)
  4. an exact, case-insensitive name match
  5. otherwise created — only when name is stated

When both a person and a company resolve, their membership is recorded.

If the platform identity and a natural key (email/domain) resolve to different entities, the identity match wins and nothing is merged; the other entity is returned as conflictWith — a probable duplicate to reconcile deliberately.

Removing a stored link is not part of this endpoint; it will ship separately.

POST/identify
Authorization
AuthorizationBearer token · headerrequired

Organization API key (modem_…).

Header parameters
Idempotency-Keystring

Replays a successful mutating request for 24 hours. Reuse with a different payload returns 409.

max length 255
Request body
requiredapplication/json
identificationsobject[]required
min items 1 · max items 50
Show properties
Array of object
companyobject
Show properties
descriptionstring
min length 1
domainsstring[]

Natural keys. Matches (or create-seeds) a company by domain. A free-mail domain never matches, creates, or is stamped (no signal), but does not suppress name-keyed creation.

max items 10
identityobject

Platform pointer. Matched identity-first; upserted onto the matched/created company.

Show properties
platformstringrequired

Source platform slug (e.g. "stripe", "salesforce").

matches ^[a-z0-9]+(?:-[a-z0-9]+)*$
platformIdstringrequired

The record id on the platform (e.g. a Stripe customer id like "cus_…").

min length 1
logoUrlstring<uri>
namestring

Enables creation when no match is found.

min length 1
overwritestring[]

Scalar fields to overwrite even when already populated. Default is set-once.

personobject
Show properties
avatarUrlstring<uri>
descriptionstring
min length 1
displayNamestring

Enables creation when no match is found.

min length 1
emailstring<email>

Natural key. Matches a person by exact, lowercased email. Never creates on its own.

identityobject

Platform pointer. Matched identity-first; upserted onto the matched/created person.

Show properties
platformstringrequired

Source platform slug (e.g. "stripe", "salesforce").

matches ^[a-z0-9]+(?:-[a-z0-9]+)*$
platformIdstringrequired

The record id on the platform (e.g. a Stripe customer id like "cus_…").

min length 1
overwritestring[]

Scalar fields to overwrite even when already populated. Default is set-once.

Responses
200

OK

resultsobject[]required
Show properties
Array of object
companyobject | nullrequired
Show properties
Any of:
object
conflictWithstring | nullrequired

A probable duplicate surfaced as a merge candidate: the platform identity resolved to id, but the natural key (email/domain) is owned by this different existing entity. identify never merges — it's left for a deliberate merge. Null when there was no conflict.

Show properties
Any of:
string
string
null
null
createdbooleanrequired
idstringrequired
null
null
membershipLinkedbooleanrequired
personobject | nullrequired
Show properties
Any of:
object
conflictWithstring | nullrequired

A probable duplicate surfaced as a merge candidate: the platform identity resolved to id, but the natural key (email/domain) is owned by this different existing entity. identify never merges — it's left for a deliberate merge. Null when there was no conflict.

Show properties
Any of:
string
string
null
null
createdbooleanrequired
idstringrequired
null
null
400

Invalid request (validation failed).

codestringrequired

Machine-readable error code, e.g. NOT_FOUND.

dataany

Optional structured error details.

definedbooleanrequired

True if the error was declared in the procedure contract.

messagestringrequired

Human-readable error message.

statusintegerrequired

HTTP status code.

401

Missing or invalid API key.

codestringrequired

Machine-readable error code, e.g. NOT_FOUND.

dataany

Optional structured error details.

definedbooleanrequired

True if the error was declared in the procedure contract.

messagestringrequired

Human-readable error message.

statusintegerrequired

HTTP status code.

403

The API key does not have access to this resource.

codestringrequired

Machine-readable error code, e.g. NOT_FOUND.

dataany

Optional structured error details.

definedbooleanrequired

True if the error was declared in the procedure contract.

messagestringrequired

Human-readable error message.

statusintegerrequired

HTTP status code.

404

The requested resource was not found.

codestringrequired

Machine-readable error code, e.g. NOT_FOUND.

dataany

Optional structured error details.

definedbooleanrequired

True if the error was declared in the procedure contract.

messagestringrequired

Human-readable error message.

statusintegerrequired

HTTP status code.

409

The request conflicts with an existing resource or idempotency operation.

codestringrequired

Machine-readable error code, e.g. NOT_FOUND.

dataany

Optional structured error details.

definedbooleanrequired

True if the error was declared in the procedure contract.

messagestringrequired

Human-readable error message.

statusintegerrequired

HTTP status code.

429

Rate limit exceeded.

codestringrequired

Machine-readable error code, e.g. NOT_FOUND.

dataany

Optional structured error details.

definedbooleanrequired

True if the error was declared in the procedure contract.

messagestringrequired

Human-readable error message.

statusintegerrequired

HTTP status code.

500

Internal server error.

codestringrequired

Machine-readable error code, e.g. NOT_FOUND.

dataany

Optional structured error details.

definedbooleanrequired

True if the error was declared in the procedure contract.

messagestringrequired

Human-readable error message.

statusintegerrequired

HTTP status code.

Try it
Server
Authorization
Parameters
Bodyapplication/json
Request
curl -X POST 'https://api.modem.dev/v1/identify' \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "identifications": [
    {
      "company": {
        "description": "string",
        "domains": [
          "string"
        ],
        "identity": {
          "platform": "string",
          "platformId": "string"
        },
        "logoUrl": "http://example.com",
        "name": "string",
        "overwrite": [
          "description"
        ]
      },
      "person": {
        "avatarUrl": "http://example.com",
        "description": "string",
        "displayName": "string",
        "email": "user@example.com",
        "identity": {
          "platform": "string",
          "platformId": "string"
        },
        "overwrite": [
          "avatarUrl"
        ]
      }
    }
  ]
}'
Response
{
  "results": [
    {
      "company": {
        "conflictWith": "string",
        "created": true,
        "id": "string"
      },
      "membershipLinked": true,
      "person": {
        "conflictWith": "string",
        "created": true,
        "id": "string"
      }
    }
  ]
}

Was this page helpful?