Skip to main content
Custom Objects let you model anything that isn’t a Person, Company, or Deal — without waiting for us to ship native support. Each custom object has a slug, a display name, and records. Records can have their own schema (the engine works the same way as for native objects — pass the custom object’s id as :object_type when defining attributes).

Endpoints

MethodPathPurpose
GET/custom-objectsList definitions
POST/custom-objectsDefine a new custom object
GET/custom-objects/:slugGet one definition
GET/custom-objects/:slug/recordsList records, paginated
POST/custom-objects/:slug/recordsCreate a record
PATCH/custom-objects/:slug/records/:idUpdate a record
DELETE/custom-objects/:slug/records/:idDelete a record

Define a custom object

curl -X POST $SALTY_API/custom-objects \
  -H "Authorization: Bearer $SALTY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "invoices",
    "display_name": "Invoice",
    "display_name_plural": "Invoices"
  }'
Slug rules: lowercase, snake_case, starts with a letter, max 64 chars. Duplicate slug → 409 custom_object_exists.

Add a schema for the new object

The schema endpoints work on custom objects too — pass the custom object’s UUID (not its slug) as :object_type:
curl -X POST $SALTY_API/schema/<custom-object-id>/attributes \
  -H "Authorization: Bearer $SALTY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "attribute_key": "status",
    "display_name": "Status",
    "data_type": "enum",
    "enum_values": ["unpaid", "paid"]
  }'

Create a record

curl -X POST $SALTY_API/custom-objects/invoices/records \
  -H "Authorization: Bearer $SALTY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "amount": 12500,
      "currency": "USD",
      "status": "paid"
    }
  }'
data is validated against any attribute definitions you’ve created for the custom object’s UUID. Unknown keys pass through (lenient). If you defined status as an enum and try "status": "overdue":
{
  "error": {
    "type": "invalid_request",
    "code": "attribute_enum_invalid",
    "message": "\"overdue\" is not a valid value for \"status\"; expected one of: unpaid, paid",
    "param": "status"
  }
}

List records

curl "$SALTY_API/custom-objects/invoices/records?limit=50" \
  -H "Authorization: Bearer $SALTY_API_KEY"
Standard { data, next_cursor } envelope. See Pagination.