cypress.DOCS
Log inRegister
Cypress Docs
Developers

Your own ids

Push and look up vehicles, listings, contacts, businesses, deals and tasks by the ids your own systems use, so a bridge keeps no mapping table of its own.

TL;DRAI summary

You can use your own existing IDs for vehicles, listings, and other records in Cypress. This chapter shows you how to send your IDs to Cypress and how to look up records using your IDs, so you don't have to keep track of Cypress's internal IDs.

Dive deeper:

Your systems already have ids for what they send us: a unit number in a fleet database, a stock number in a DMS, a customer number in an ERP. Send them as externalIds, and Cypress keeps the mapping for you: you push and look up by your own id, and never keep a table of Cypress ids on your side. Since 1.5.0.

The shape

"externalIds": [
  { "source": "fox-access", "id": "U-10442" },
  { "source": "erp", "id": "CUST-0093" }
]

source is your name for the system: letters, digits, dot, dash or underscore, up to 40 characters. id is that system's id for the record, up to 128 characters. A record has one id per source, at most ten sources.

The rules

RuleWhat it means
Unique per source in your organizationTwo contacts of your book can't both be erp:CUST-0093. Another organization's same id is its own.
Set or replaced per sourceSending erp:CUST-0094 for a contact that had erp:CUST-0093 replaces it.
Never removed by omissionA write that leaves externalIds out, or names fewer sources, keeps the ids it doesn't mention.
Refused, not movedAn id another record of the same kind holds answers 409 EXTERNAL_ID_TAKEN, and nothing is written. taken names the record that holds it (vehicleId, listingId, contactId, businessId, dealId or taskId).
Gone with the recordDeleting a record deletes its ids.

A contact or a business POST opens the record your book already has (the same address, the same name or domain). If that record holds the id you send, the write goes ahead; if another record does, it is refused.

Where they go

RecordSet onRead onLook up
VehiclePOST /api/v1/vehicles, /vehicles/bulk, PATCH /vehicles/{id}every vehicleGET /api/v1/vehicles?externalId=<source>:<id>
ListingPOST /api/v1/listings, PATCH /listings/{id}every listingGET /api/v1/listings?externalId=
ContactPOST /api/v1/contacts, PATCH /contacts/{id}every contactGET /api/v1/contacts?externalId=
BusinessPOST /api/v1/businesses, PATCH /businesses/{id}every businessGET /api/v1/businesses?externalId=
DealPOST /api/v1/deals, PATCH /deals/{id}every dealGET /api/v1/deals?externalId=
TaskPOST /api/v1/tasks, PATCH /tasks/{id}every taskGET /api/v1/tasks?externalId=

A lookup answers a list of zero or one item, so "not mapped yet" is an empty list, never a 404. The first colon separates the source from the id: an id may contain colons.

A PATCH with externalIds alone changes only your ids. On a dry run (?dryRun=true), the ids are checked and listed in the changes, and nothing is written.

Many at once

POST /api/v1/contacts/bulk, /businesses/bulk, /tasks/bulk and /listings/bulk take up to 100 rows, { "items": [ … ] }, each the body a single POST takes. A listing row that names a listing changes its prices and channels under the same price rules as a PATCH (its vehicle and listingMode stay); one that names none is listed on its vehicleId. Each row is matched by its externalIds:

The row's idsWhat happensRow status
Name a record of your organizationThat record is changed, as a PATCH would change it200
Name noneA new record is made (a contact or business may open the one your book already has, by address or name, as a POST does)201 (200 when opened)
Name two different recordsThe row is refused, EXTERNAL_ID_TAKEN409

Every row goes through the same rules as one at a time, in order, so a later row sees what an earlier one wrote. One bad row never fails the batch: it answers its own status, code and errors, and the request answers 200 with created, updated and refused counts. A matched task changes its title, notes, due date, channel, assignee and business; what else it is about is set when it is made. ?dryRun=true checks every row and writes nothing. An Idempotency-Key makes a retry of the whole request answer the same, once.

{
  "items": [
    { "index": 0, "status": 201, "id": "cm…" },
    { "index": 1, "status": 200, "id": "cm…" },
    { "index": 2, "status": 422, "code": "INVALID", "errors": ["email: Required"] }
  ],
  "created": 1, "updated": 1, "refused": 1
}

Two writers at once

When two pushes claim the same id at the same moment, the first one keeps it. The other record is still written, and its answer carries a warnings line naming the ids that were not saved. Look the id up, then fix the mapping on your side.