SalesOS

Custom objects and fields

Model your own entities and fields, consistently across REST, GraphQL and webhooks.

Custom fields on standard objects

Define fields on leads, contacts, accounts, opportunities, products and quotes with POST /v1/custom-fields. Read a record's values with GET /v1/custom-fields/values/{entityType}/{entityId}. Formula and roll-up fields are computed when read and can't be written.

On the core list endpoints

GET /v1/leads, /contacts, /accounts and /opportunities accept:

ParameterEffect
withCustomFields=trueEach row gains customFields: { <apiName>: value } (stored fields you can read)
sortBy=customFields.<apiName>Sort by a custom field (server-side, across every page)
customFields=[{"field":"region","operator":"eq","value":"EMEA"}]Filter by custom fields (JSON, up to 10, ANDed)

Operators: eq, neq, contains, gt, gte, lt, lte, is_empty, is_not_empty. Filters and sorts are ANDed onto the list's own visibility, so they only ever narrow it. Sorting or filtering resolves the matching ids first and refuses with 400 CUSTOM_FIELD_SORT_TOO_BROAD / CUSTOM_FIELD_FILTER_TOO_BROAD beyond 10,000; add another filter. A field your profile can't read is 403 FIELD_NOT_READABLE; formula and roll-up fields can't be sorted or filtered.

Write values on one record with PUT /v1/record-custom-fields/{LEAD|CONTACT|ACCOUNT|OPPORTUNITY}/{id} and {"values": {"region": "EMEA", "renewal_date": "2026-12-01"}} (null clears a value). The same rule as the record's own update applies: you own it, it's shared with you for edit, or you're an admin; plus your profile's edit permission on the object and field security on each field (403 FIELD_NOT_EDITABLE).

Field-level security keys for these fields are customFields.<apiName>.

Custom objects

OperationEndpoint
List definitionsGET /v1/custom-objects
Create a definitionPOST /v1/custom-objects
Add a fieldPOST /v1/custom-objects/{object}/fields
List recordsGET /v1/custom-objects/{object}/records
Create a recordPOST /v1/custom-objects/{object}/records with {"data": {"title": "Q4 rollout", "budget": 15000}}
Get a recordGET /v1/custom-objects/{object}/records/{recordId}
Update a recordPATCH /v1/custom-objects/{object}/records/{recordId} (merges data)
Update one field on many recordsPATCH /v1/custom-objects/{object}/records with {"ids": [...], "field": "status", "value": "Done"} (≤200 ids; each goes through the normal update)
Delete a recordDELETE /v1/custom-objects/{object}/records/{recordId}
Child related lists of a recordGET /v1/custom-objects/{object}/records/{recordId}/related
Custom-object related lists of a standard recordGET /v1/custom-objects/related/{entityType}/{entityId}

{object} is the object's id or API name.

Listing records

GET …/records?page=1&limit=25&sortBy=budget&sortOrder=desc&search=rollout&filters=<json>&owner=me&ids=a,b returns { data, pagination: { page, limit, total, totalPages, hasMore } }. filters is a JSON array of { "field", "operator", "value" } using the operators above (plus not_contains, starts_with, between, in, not_in); sortBy takes a field API name or createdAt / updatedAt / ownerName. Each record carries id, data, ownerId, owner, timestamps and lookups: { <field>: { id, object, label } } for its lookup fields.

Relationships

LOOKUP and MASTER_DETAIL fields point at a standard object (LEAD, CONTACT, ACCOUNT, OPPORTUNITY, TASK, CASE) or another custom object (custom:<apiName>); the value in data is the target record's id. A detail record of a MASTER_DETAIL is visible to whoever can see its master. The related endpoints group the records that point at a record by object and field, with the first few rows and a total each.

Permissions

Records follow the same rules as the core objects: the custom:<apiName> module on the caller's profile (read / create / edit / delete and OWN / TEAM / ALL data access), the owner's reporting tree, record shares and master-detail inheritance. Field-level security uses custom:<apiName> as the entity and the field API name as the field; hidden fields are left out of responses and writes to read-only fields are 403 FIELD_NOT_EDITABLE. API keys need READ_CUSTOM_OBJECTS or WRITE_CUSTOM_OBJECTS.

Field history

Fields with trackHistory record every change. GET /v1/custom-object-history/{object}/{recordId} returns { data: [{ field, oldValue, newValue, changedBy, changedByName, changedAt }] }, newest first, for anyone who can read the record (fields hidden by their profile are left out). The admin audit trail has the same rows under entity type custom:<apiName>.

Page layouts and saved views

Use custom:<apiName> wherever the API takes an object type: page layouts (PUT /v1/page-layouts with objectType: "custom:project"; built-in tabs details, related, activity; rail fields are the object's field API names), saved list views (entity: "custom:project") and recently viewed records.

Reports and dashboards

POST /v1/custom-reports/preview and saved reports accept type: "custom:<apiName>"; GET /v1/custom-reports/fields/custom:<apiName> lists its fields. Standard report types also offer their custom fields as cf:<apiName> (columns, filters, group by and numeric aggregates). Dashboard widgets take dataSource: "custom:<apiName>".

Importing

Send rows to the Bulk API with object: "custom:<apiName>". To turn names into lookup ids first, POST /v1/import-export/custom-objects/{apiName}/resolve-lookups with {"field": "account", "values": ["Acme", "[email protected]"]} returns { resolved: { value: id }, unresolved, ambiguous }, limited to records you can see.

One record shape everywhere

GraphQL and webhook payloads share one record shape, so a record looks the same whichever way you receive it:

{
  "id": "clx...",
  "object": "project",
  "objectId": "clx-def...",
  "ownerId": "usr_...",
  "organizationId": "org_...",
  "createdAt": "2026-10-01T09:30:00.000Z",
  "updatedAt": "2026-10-01T09:30:00.000Z",
  "data": { "title": "Q4 rollout", "budget": 15000, "active": true }
}

Standard records carry customFields keyed by field API name. Dates are ISO strings, money is a number, and secrets are never included.

See GraphQL for typed per-object queries.

On this page