Custom Objects & Associations
Custom objects hold data that doesn’t fit on a contact, such as pets or vehicles. Each object has a schema (its key, labels, and fields) and any number of records. An association defines how two kinds of object relate, for example a pet and its owner, and a relation links one record to another under an association.
Base URL: https://services.smbcrm.com · Version header: v3
The endpoints on this page use eight scopes. See Scopes for how to request them.
| Scope | Allows |
|---|---|
objects/schema.readonly |
List objects and get an object’s schema. |
objects/schema.write |
Update an object’s labels, description, and searchable fields. |
objects/record.readonly |
Search records and get a record. |
objects/record.write |
Create, update, and delete records. |
associations.readonly |
List and get associations. |
associations.write |
Create, update, and delete associations. |
associations/relation.readonly |
Get the relations of a record. |
associations/relation.write |
Create and delete relations. |
Object keys
Section titled “Object keys”Every object has a key, and the schema and record endpoints on this page take it in the URL
path. A custom object’s key starts with custom_objects., for example custom_objects.pet. Standard
objects such as contacts and opportunities have keys too. List objects
returns the key of each object in the location. You can also read a custom object’s key on
its details page under Settings in the SMBcrm app.
Field keys and the objectKey in field requests use a slightly different prefix, such as
custom_object.pet and custom_object.pet.name. See
Custom Fields, Values & Tags.
Object schemas
Section titled “Object schemas”A schema describes an object: its key, labels, description, and fields.
List objects
Section titled “List objects”Returns the standard objects in the location, such as contacts and opportunities, together
with your custom objects. Read the key of each entry: the schema and record endpoints on
this page take an object key.
| Query parameter | Type | Required | Description |
|---|---|---|---|
locationId |
string | Yes | The location ID. |
curl "https://services.smbcrm.com/objects/?locationId=<location_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "objects": [ { "id": "<object_id>", "standard": false, "key": "custom_objects.pet", "labels": { "singular": "Pet", "plural": "Pets" }, "description": "Pets we board and groom", "locationId": "<location_id>", "primaryDisplayProperty": "custom_objects.pet.name", "type": "USER_DEFINED", "dateAdded": "2026-10-08T15:04:00.000Z", "dateUpdated": "2026-10-08T15:04:00.000Z" } ]}Every endpoint that returns an object uses this shape:
| Field | Type | Description |
|---|---|---|
id |
string | The schema ID. |
standard |
boolean | false for custom objects, true for standard objects such as contacts and opportunities. |
key |
string | The object key. Custom object keys start with custom_objects.. |
labels |
object | The display names: singular and plural. |
description |
string | The object’s description. |
locationId |
string | The location the object belongs to. |
primaryDisplayProperty |
string | The field that identifies a record in the SMBcrm app. |
type |
string | USER_DEFINED or SYSTEM_DEFINED. |
dateAdded |
string | When the object was added. |
dateUpdated |
string | When the object was last updated. |
Get an object
Section titled “Get an object”Returns one object. Add fetchProperties=true to include the object’s fields in the
fields array.
| Parameter | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | Path parameter. The object key, for example custom_objects.pet. |
locationId |
string | Yes | Query parameter. The location ID. |
fetchProperties |
string | No | Query parameter. Send true to include the object’s fields. |
curl "https://services.smbcrm.com/objects/custom_objects.pet?locationId=<location_id>&fetchProperties=true" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "object": { "id": "<object_id>", "standard": false, "key": "custom_objects.pet", "labels": { "singular": "Pet", "plural": "Pets" }, "description": "Pets we board and groom", "locationId": "<location_id>", "primaryDisplayProperty": "custom_objects.pet.name", "type": "USER_DEFINED", "dateAdded": "2026-10-08T15:04:00.000Z", "dateUpdated": "2026-10-08T15:04:00.000Z" }, "cache": false, "fields": [ { "id": "<field_id>", "locationId": "<location_id>", "name": "Name", "fieldKey": "custom_object.pet.name", "objectKey": "custom_object.pet", "dataType": "TEXT", "parentId": "<folder_id>", "showInForms": true, "dateAdded": "2026-10-08T15:04:00.000Z", "dateUpdated": "2026-10-08T15:04:00.000Z" }, { "id": "<field_id_2>", "locationId": "<location_id>", "name": "Age", "fieldKey": "custom_object.pet.age", "objectKey": "custom_object.pet", "dataType": "NUMERICAL", "parentId": "<folder_id>", "showInForms": true, "dateAdded": "2026-10-08T15:04:00.000Z", "dateUpdated": "2026-10-08T15:04:00.000Z" } ]}object has the fields listed under List objects. cache is true when
the response was served from cache. Each entry in fields has these fields:
| Field | Type | Description |
|---|---|---|
id |
string | The field ID. |
name |
string | The field name. |
fieldKey |
string | The field key, for example custom_object.pet.name. |
objectKey |
string | The key of the object the field belongs to. |
dataType |
string | One of TEXT, LARGE_TEXT, NUMERICAL, PHONE, MONETORY, CHECKBOX, SINGLE_OPTIONS, MULTIPLE_OPTIONS, DATE, TEXTBOX_LIST, FILE_UPLOAD, or RADIO. |
parentId |
string | The ID of the folder the field sits in. |
showInForms |
boolean | Whether the field appears in forms. |
description |
string | The field’s description. |
placeholder |
string | The field’s placeholder text. |
options |
array | The choices for option fields. Each has a key and a label, and RADIO options can also have a url. |
allowCustomOption |
boolean | On RADIO fields, whether a record can hold a value that isn’t one of the options. |
acceptedFormats |
string | On file upload fields, the allowed format: .pdf, .docx, .doc, .jpg, .jpeg, .png, .gif, .csv, .xlsx, .xls, or all. |
maxFileLimit |
number | On file upload fields, the maximum number of files. |
locationId |
string | The location the field belongs to. |
dateAdded |
string | When the field was added. |
dateUpdated |
string | When the field was last updated. |
Update an object
Section titled “Update an object”Changes an object’s labels and description, and sets which fields
record search matches against. locationId and searchableProperties
are required. On a standard object, this endpoint updates the searchable fields.
| Parameter | Type | Required | Description |
|---|---|---|---|
key |
string | Yes | Path parameter. The object key, for example custom_objects.pet. |
locationId |
string | Yes | Body field. The location ID. |
searchableProperties |
array of strings | Yes | Body field. The field keys that record search matches against. Use the fieldKey values from Get an object. |
labels |
object | No | Body field. The display names: singular and plural. |
description |
string | No | Body field. The object’s description. |
curl -X PUT https://services.smbcrm.com/objects/custom_objects.pet \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "locationId": "<location_id>", "labels": { "singular": "Pet", "plural": "Pets" }, "description": "Pets we board and groom", "searchableProperties": ["custom_object.pet.name"] }'{ "object": { "id": "<object_id>", "standard": false, "key": "custom_objects.pet", "labels": { "singular": "Pet", "plural": "Pets" }, "description": "Pets we board and groom", "locationId": "<location_id>", "primaryDisplayProperty": "custom_objects.pet.name", "type": "USER_DEFINED", "dateAdded": "2026-10-08T15:04:00.000Z", "dateUpdated": "2026-10-08T15:10:00.000Z" }}Records
Section titled “Records”A record is one entry in an object, such as one pet. The record endpoints work on custom
objects and on the standard Business object. In each path, schemaKey is the object key, for
example custom_objects.pet.
A record’s properties is an object that holds the field values. Each key is a field name,
which is the last part of the field’s fieldKey: the field custom_object.pet.name is
name in properties. The value format depends on the field type:
| Field type | Value |
|---|---|
TEXT, LARGE_TEXT |
A string. |
PHONE |
A string in international format, for example +15125550142. |
NUMERICAL |
A number. |
MONETORY |
An object with currency and value, for example { "currency": "default", "value": 100 }. |
DATE |
A string in YYYY-MM-DD format. |
MULTIPLE_OPTIONS |
An array of strings. |
FILE_UPLOAD |
An array of objects, each with a url. |
TEXTBOX_LIST |
One key per option, written as <field name>.<option key>, each with a string value. |
Create a record
Section titled “Create a record”Adds a record to an object. locationId and properties are required.
| Parameter | Type | Required | Description |
|---|---|---|---|
schemaKey |
string | Yes | Path parameter. The object key, for example custom_objects.pet. |
locationId |
string | Yes | Body field. The location ID. |
properties |
object | Yes | Body field. The field values, keyed by field name. |
curl -X POST https://services.smbcrm.com/objects/custom_objects.pet/records \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "locationId": "<location_id>", "properties": { "name": "Buddy", "age": 4 } }'{ "record": { "id": "<record_id>", "owner": [], "followers": [], "properties": { "name": "Buddy", "age": 4 }, "dateAdded": "2026-10-08T15:04:00.000Z", "dateUpdated": "2026-10-08T15:04:00.000Z" }}Every endpoint that returns a single record uses this shape:
| Field | Type | Description |
|---|---|---|
id |
string | The record ID. Use it to get, update, and delete the record and to link it with a relation. |
owner |
array of strings | The user ID of the record’s owner. It holds at most one ID and applies to custom objects only. See Users. |
followers |
array of strings | The user IDs of the record’s followers, up to 10. |
properties |
object | The field values, keyed by field name. |
dateAdded |
string | When the record was added. |
dateUpdated |
string | When the record was last updated. |
Search records
Section titled “Search records”Finds records in one object. query is matched against the object’s searchable fields,
which you set with Update an object. To search one field, put its name
before the value, as in name:Buddy. All five body fields are required.
page and pageLimit set the page and its size. searchAfter is a cursor: send an empty
array on the first request, or the searchAfter value of the last record you received to
continue after it.
| Parameter | Type | Required | Description |
|---|---|---|---|
schemaKey |
string | Yes | Path parameter. The object key, for example custom_objects.pet. |
locationId |
string | Yes | Body field. The location ID. |
page |
number | Yes | Body field. The page number. |
pageLimit |
number | Yes | Body field. The number of records per page. |
query |
string | Yes | Body field. The search text, for example name:Buddy. |
searchAfter |
array | Yes | Body field. The pagination cursor. Send [] for the first page. |
curl -X POST https://services.smbcrm.com/objects/custom_objects.pet/records/search \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "locationId": "<location_id>", "page": 1, "pageLimit": 10, "query": "name:Buddy", "searchAfter": [] }'{ "records": [ { "id": "<record_id>", "owner": [], "followers": [], "properties": { "name": "Buddy", "age": 4 }, "createdAt": "2026-10-08T15:04:00.000Z", "updatedAt": "2026-10-08T15:04:00.000Z", "locationId": "<location_id>", "objectId": "<object_id>", "objectKey": "custom_objects.pet", "createdBy": { "channel": "WEB_USER", "createdAt": "2026-10-08T15:04:00.000Z", "source": "PUBLIC_API", "sourceId": "<user_id>" }, "lastUpdatedBy": { "channel": "WEB_USER", "createdAt": "2026-10-08T15:04:00.000Z", "source": "PUBLIC_API", "sourceId": "<user_id>" }, "searchAfter": [1791471840000, "<record_id>"] } ], "total": 1}total is the total number of records. Search results name the timestamps createdAt and
updatedAt, where the other record endpoints use dateAdded and dateUpdated. Each record
also carries these fields:
| Field | Type | Description |
|---|---|---|
objectId |
string | The ID of the object schema the record belongs to. |
objectKey |
string | The key of the object the record belongs to. |
createdBy |
object | Who created the record: channel, createdAt, source, and sourceId (a user or resource ID). |
lastUpdatedBy |
object | Who last updated the record, with the same four fields. |
searchAfter |
array | The cursor for continuing a search after this record. |
Get a record
Section titled “Get a record”| Parameter | Type | Required | Description |
|---|---|---|---|
schemaKey |
string | Yes | Path parameter. The object key, for example custom_objects.pet. |
id |
string | Yes | Path parameter. The record ID. |
curl https://services.smbcrm.com/objects/custom_objects.pet/records/<record_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "record": { "id": "<record_id>", "owner": ["<user_id>"], "followers": [], "properties": { "name": "Buddy", "age": 4 }, "dateAdded": "2026-10-08T15:04:00.000Z", "dateUpdated": "2026-10-08T15:04:00.000Z" }}Update a record
Section titled “Update a record”Changes the values on an existing record. Send locationId in the query string and the new
values in a properties object in the body.
| Parameter | Type | Required | Description |
|---|---|---|---|
schemaKey |
string | Yes | Path parameter. The object key, for example custom_objects.pet. |
id |
string | Yes | Path parameter. The record ID. |
locationId |
string | Yes | Query parameter. The location ID. |
properties |
object | Yes | Body field. The field values to set, keyed by field name. |
curl -X PUT "https://services.smbcrm.com/objects/custom_objects.pet/records/<record_id>?locationId=<location_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "properties": { "age": 5 } }'{ "record": { "id": "<record_id>", "owner": ["<user_id>"], "followers": [], "properties": { "name": "Buddy", "age": 5 }, "dateAdded": "2026-10-08T15:04:00.000Z", "dateUpdated": "2026-10-08T15:12:00.000Z" }}Delete a record
Section titled “Delete a record”| Parameter | Type | Required | Description |
|---|---|---|---|
schemaKey |
string | Yes | Path parameter. The object key, for example custom_objects.pet. |
id |
string | Yes | Path parameter. The record ID. |
curl -X DELETE https://services.smbcrm.com/objects/custom_objects.pet/records/<record_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "id": "<record_id>", "success": true}id is the ID of the deleted record, and success is true when the deletion worked.
Associations
Section titled “Associations”An association defines how two kinds of object relate. It has a unique key, the key of
each of its two objects, and a label for each side. A pet-and-owner association, for example, links the
custom_objects.pet object to contact, with the labels pet and owner. The association
doesn’t link any particular records yet. You do that with relations.
Associations you create have the type USER_DEFINED. Built-in associations have the type
SYSTEM_DEFINED. An association has these fields:
| Field | Type | Description |
|---|---|---|
id |
string | The association ID. |
locationId |
string | The location the association belongs to. |
key |
string | The association’s unique key. |
firstObjectKey |
string | The key of the first object, for example custom_objects.pet. |
firstObjectLabel |
string | The label for the first object’s side of the association. |
secondObjectKey |
string | The key of the second object, for example contact. |
secondObjectLabel |
string | The label for the second object’s side of the association. |
associationType |
string | USER_DEFINED or SYSTEM_DEFINED. |
List associations
Section titled “List associations”Returns the associations in the location. locationId, skip, and limit are all required.
| Query parameter | Type | Required | Description |
|---|---|---|---|
locationId |
string | Yes | The location ID. |
skip |
number | Yes | The number of associations to skip. |
limit |
number | Yes | The number of associations to return. |
curl "https://services.smbcrm.com/associations/?locationId=<location_id>&skip=0&limit=20" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Get an association
Section titled “Get an association”Works for both USER_DEFINED and SYSTEM_DEFINED associations.
| Parameter | Type | Required | Description |
|---|---|---|---|
associationId |
string | Yes | Path parameter. The association ID. |
curl https://services.smbcrm.com/associations/<association_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "id": "<association_id>", "locationId": "<location_id>", "key": "pet_owner", "firstObjectKey": "custom_objects.pet", "firstObjectLabel": "pet", "secondObjectKey": "contact", "secondObjectLabel": "owner", "associationType": "USER_DEFINED"}Get an association by key
Section titled “Get an association by key”Looks an association up by its key. For an association you created, that is the key you
sent when you created it.
| Parameter | Type | Required | Description |
|---|---|---|---|
key_name |
string | Yes | Path parameter. The association’s key. |
locationId |
string | Yes | Query parameter. The location ID. |
curl "https://services.smbcrm.com/associations/key/pet_owner?locationId=<location_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Get associations by object key
Section titled “Get associations by object key”Pass the key of a contact, opportunity, or custom object to find its associations.
| Parameter | Type | Required | Description |
|---|---|---|---|
objectKey |
string | Yes | Path parameter. The object key, for example custom_objects.pet. |
locationId |
string | No | Query parameter. The location ID. |
curl "https://services.smbcrm.com/associations/objectKey/custom_objects.pet?locationId=<location_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Create an association
Section titled “Create an association”Defines a new association. It supports contact to contact, contact to custom object, and
business to contact. All six body fields are required, and key must be unique.
| Body field | Type | Required | Description |
|---|---|---|---|
locationId |
string | Yes | The location ID. |
key |
string | Yes | The association’s unique key. |
firstObjectKey |
string | Yes | The key of the first object, for example custom_objects.pet. |
firstObjectLabel |
string | Yes | The label for the first object’s side of the association. |
secondObjectKey |
string | Yes | The key of the second object, for example contact. |
secondObjectLabel |
string | Yes | The label for the second object’s side of the association. |
curl -X POST https://services.smbcrm.com/associations/ \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "locationId": "<location_id>", "key": "pet_owner", "firstObjectKey": "custom_objects.pet", "firstObjectLabel": "pet", "secondObjectKey": "contact", "secondObjectLabel": "owner" }'{ "id": "<association_id>", "locationId": "<location_id>", "key": "pet_owner", "firstObjectKey": "custom_objects.pet", "firstObjectLabel": "pet", "secondObjectKey": "contact", "secondObjectLabel": "owner", "associationType": "USER_DEFINED"}Keep the id. You pass it as associationId when you create a relation.
Update an association
Section titled “Update an association”Updates the two labels. Nothing else on the association changes. Both labels are required.
| Parameter | Type | Required | Description |
|---|---|---|---|
associationId |
string | Yes | Path parameter. The association ID. |
firstObjectLabel |
string | Yes | Body field. The new label for the first object’s side. |
secondObjectLabel |
string | Yes | Body field. The new label for the second object’s side. |
curl -X PUT https://services.smbcrm.com/associations/<association_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "firstObjectLabel": "pet", "secondObjectLabel": "guardian" }'{ "id": "<association_id>", "locationId": "<location_id>", "key": "pet_owner", "firstObjectKey": "custom_objects.pet", "firstObjectLabel": "pet", "secondObjectKey": "contact", "secondObjectLabel": "guardian", "associationType": "USER_DEFINED"}Delete an association
Section titled “Delete an association”Only USER_DEFINED associations can be deleted.
| Parameter | Type | Required | Description |
|---|---|---|---|
associationId |
string | Yes | Path parameter. The association ID. |
curl -X DELETE https://services.smbcrm.com/associations/<association_id> \ -H "Authorization: Bearer <token>" \ -H "Version: v3"{ "deleted": true, "id": "<association_id>", "message": "Association deleted successfully"}Relations
Section titled “Relations”A relation links two records under an association. Records go in the order the association
lists its objects: firstRecordId is a record of the association’s first object, and
secondRecordId is a record of its second object. For a pet-and-owner association with the
pet first, firstRecordId is the pet record’s ID and secondRecordId is the contact’s ID.
A contact’s record ID is its contact ID. See Contacts. An
association can also use the Business object as one side, so business records can be linked
too.
Create a relation
Section titled “Create a relation”All four body fields are required.
| Body field | Type | Required | Description |
|---|---|---|---|
locationId |
string | Yes | The location ID. |
associationId |
string | Yes | The ID of the association to link the records under. |
firstRecordId |
string | Yes | The ID of the record of the association’s first object. |
secondRecordId |
string | Yes | The ID of the record of the association’s second object. |
curl -X POST https://services.smbcrm.com/associations/relations \ -H "Authorization: Bearer <token>" \ -H "Version: v3" \ -H "Content-Type: application/json" \ -d '{ "locationId": "<location_id>", "associationId": "<association_id>", "firstRecordId": "<pet_record_id>", "secondRecordId": "<contact_id>" }'A successful call returns 201 Created.
Get a record’s relations
Section titled “Get a record’s relations”Returns the relations that include a record. Pass a custom object record’s ID or a
contact’s ID in the path. locationId, skip, and limit are required. Add
associationIds to limit the result to specific associations. To delete a relation, pass
its id as relationId to Delete a relation.
| Parameter | Type | Required | Description |
|---|---|---|---|
recordId |
string | Yes | Path parameter. The record ID. |
locationId |
string | Yes | Query parameter. The location ID. |
skip |
number | Yes | Query parameter. The number of relations to skip. |
limit |
number | Yes | Query parameter. The number of relations to return. |
associationIds |
array of strings | No | Query parameter. Only return relations that belong to these associations. |
curl "https://services.smbcrm.com/associations/relations/<record_id>?locationId=<location_id>&skip=0&limit=20" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"Delete a relation
Section titled “Delete a relation”Removes one relation.
| Parameter | Type | Required | Description |
|---|---|---|---|
relationId |
string | Yes | Path parameter. The relation ID. |
locationId |
string | Yes | Query parameter. The location ID. |
curl -X DELETE "https://services.smbcrm.com/associations/relations/<relation_id>?locationId=<location_id>" \ -H "Authorization: Bearer <token>" \ -H "Version: v3"IDs that other endpoints use
Section titled “IDs that other endpoints use”| ID | Where it comes from | Where you use it |
|---|---|---|
Object key |
List objects | The path of every schema and record endpoint, firstObjectKey and secondObjectKey on associations, and the object field endpoints. |
Record id |
Create, search, or get a record | Get, update, and delete a record. firstRecordId and secondRecordId on a relation, and recordId when you get a record’s relations. |
| Contact ID | Contacts | A relation’s firstRecordId or secondRecordId when the association’s object is contact. |
Association id |
List or create an association | Update and delete an association, and associationId on a relation. |
User ID in owner and followers |
Users | The owner and followers shown on a record. |
Related
Section titled “Related”- Custom Fields, Values & Tags: add and change the fields on a custom object.
- Contacts: contacts are the most common association target, and a contact’s ID is its record ID in a relation.
- Users: look up the user IDs that appear in
ownerandfollowers. - Scopes: the full list of scopes your token can request.
- Errors & Troubleshooting: status codes and error response shapes.
