Creates or updates a record using a unique attribute to find an existing match.
200 is returned.201 is returned.This is the recommended endpoint for bulk imports and sync jobs.
Required scope: crm:write
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"
}
}Creates or updates a record depending on whether a matching record already exists. This is the recommended endpoint for sync pipelines and bulk imports.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.
200 OK.201 Created.| Parameter | Type | Description |
|---|---|---|
objectSlug | string | The slug of the custom CRM object to assert into (e.g. products, deals). |
| Parameter | Type | Required | Description |
|---|---|---|---|
matchingAttribute | string | Yes | The 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. |
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
}
null on create, and left unchanged on update.
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
sku = <value from body>.
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
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.
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.
PUT /v2/crm/products?matchingAttribute=sku
{
"sku": "JACKET-042",
"price": 89,
"inventory_count": 200,
"in_stock": true
}
| Status | Meaning |
|---|---|
201 Created | No match was found; a new record was created. |
200 OK | A matching record was found and updated. |
Slug of the custom CRM object.
Attribute slug to use when searching for an existing record. Uses exact equality matching.
Flat object of attribute slug → value pairs.
Updated — a record with the matching attribute value was found and updated
true
200
A record for a custom CRM object.
Hide child attributes
Unique identifier for the record.
"c1d2e3f4-a5b6-7890-cdef-123456789012"
Slug of the CRM object this record belongs to.
"products"
Key/value pairs for the custom attributes defined on the object. Keys are attribute slugs.
{
"sku": "DRESS-001",
"price": 29,
"inventory_count": 150
}ISO 8601 timestamp when the record was created.
"2025-06-01T10:00:00+00:00"
ISO 8601 timestamp when the record was last updated.
"2025-06-01T12:00:00+00:00"
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"
}
}