Skip to main content
PUT
/
crm
/
{objectSlug}
Assert a CRM record (upsert)
curl --request PUT \
  --url https://api.zeeg.me/v2/crm/{objectSlug} \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "sku": "DRESS-001",
  "price": 29,
  "inventory_count": 150
}
'
{
  "success": true,
  "status": 200,
  "record": {
    "id": "c1d2e3f4-a5b6-7890-cdef-123456789012",
    "objectSlug": "products",
    "attributes": {
      "sku": "DRESS-001",
      "price": 29,
      "inventory_count": 150
    },
    "createdAt": "2025-06-01T10:00:00+00:00",
    "updatedAt": "2025-06-01T12:00:00+00:00"
  }
}

Documentation Index

Fetch the complete documentation index at: https://developer.zeeg.me/llms.txt

Use this file to discover all available pages before exploring further.

Creates or updates a record depending on whether a matching record already exists. This is the recommended endpoint for sync pipelines and bulk imports.
  • Match found → updates the existing record and returns 200 OK.
  • No match → creates a new record and returns 201 Created.

Path parameter

ParameterTypeDescription
objectSlugstringThe slug of the custom CRM object to assert into (e.g. products, deals).

Query parameter

ParameterTypeRequiredDescription
matchingAttributestringYesThe attribute slug used to look up an existing record. The API searches for a record where this attribute’s value exactly equals the value you send in the request body.

Request body

A flat JSON object of attribute slug → value pairs. The value of matchingAttribute must be included in the body — it is both the lookup key and the new value to persist.
{
  "sku": "DRESS-001",
  "price": 35,
  "inventory_count": 80
}
The entire body is applied to the record (create or update). Attributes you omit are set to null on create, and left unchanged on update.

How matching works

The API performs exact equality matching on the matchingAttribute value. Only one record is ever matched. If multiple records somehow share the same value (e.g. before you marked the attribute as unique), the first match is used.
PUT /v2/crm/products?matchingAttribute=sku
The above searches for a record where sku = <value from body>.

Choosing the right matching attribute

Pick an attribute that uniquely identifies a record in your source system — an external ID, a product SKU, a deal number, an email address. Mark it as isUnique on the object schema to prevent collisions.
PUT /v2/crm/deals?matchingAttribute=external_id
PUT /v2/crm/products?matchingAttribute=sku
PUT /v2/crm/subscriptions?matchingAttribute=stripe_subscription_id

Uniqueness constraints

If another attribute on the record is marked isUnique, the assert will fail with 400 if you try to assign a value that already belongs to a different record. You can always re-assert the same unique value back onto the same record without error.

Error: matching value is empty

If the value of matchingAttribute in the request body is null or an empty string, the API returns 400 Bad Request. Always include a non-empty value for the matching attribute.

Example: bulk product sync

Your external catalog has 10,000 products. Run assert in a loop:
PUT /v2/crm/products?matchingAttribute=sku
{
  "sku": "JACKET-042",
  "price": 89,
  "inventory_count": 200,
  "in_stock": true
}
First run: all products are created (201). Subsequent runs: existing products are updated with latest prices (200). No pre-check needed — the API handles it.

Distinguishing create vs. update

Check the HTTP status code in the response:
StatusMeaning
201 CreatedNo match was found; a new record was created.
200 OKA matching record was found and updated.

When to use this endpoint

  • Periodic sync jobs — push updated records from an external system on a schedule.
  • Webhook-driven updates — handle incoming webhooks that may create or update a record depending on whether it exists.
  • Bulk initial import — send all records from a legacy system without checking for duplicates first.
  • Idempotent writes — retry failed requests safely; asserting the same data again results in an update (200) with no duplicate.

Authorizations

Authorization
string
header
required

Path Parameters

objectSlug
string
required

Slug of the custom CRM object.

Query Parameters

matchingAttribute
string
required

Attribute slug to use when searching for an existing record. Uses exact equality matching.

Body

application/json

Flat object of attribute slug → value pairs.

Response

Updated — a record with the matching attribute value was found and updated

success
boolean
Example:

true

status
integer
Example:

200

record
object

A record for a custom CRM object.

Last modified on May 7, 2026