1. API
  2. Records

Best practices

Guidance for building with the Records API. Endpoint pages describe what each call does; this page recommends how to combine them.

See the Get Records API for the record model.

Reference by ID, not name

record_type_id and field_id are stable; names can be renamed at any time. Discover the schema once via the List record types API, cache field IDs by name, and refresh on 404. The Query API also accepts field_name — use it only for ad-hoc queries.

Use /records/query for aggregations

For counts, sums, averages, or grouped breakdowns, call the Query API. It answers in one request with its own rate-limit budget. Only reach for the List API when you need the individual rows.

Only request what you need

  • Pass record_field_ids on Get or List to return only the columns you need.
  • Artifacts come back as { id, is_artifact: true } references. On Get, Create, and Update you can pass resolve_artifacts=true to inline the contents — only do this when you need them now. List always returns references with no inline option, so fetch them lazily via Get artifact when you need the value.
  • Child records come back as ID stubs. Set include_children=true only when you need their fields. Use parent_ids on List to fetch children in one request.

Paginate deliberately

per_page defaults to 20 and caps at 500. Filter and sort server-side (filters, order_field_id), follow meta.next_page, and bound the total pages your client will walk.

Filter operator gotchas

  • IS_ANY_OF / IS_NONE_OF accept up to 10 values — prefer them over repeated EQUAL requests.
  • CONTAINS, STARTS_WITH, ENDS_WITH need three-plus characters and one pattern filter per request.
  • Values compare as strings, case-insensitively — a JSON true matches "true". Store fields as strings if you plan to filter on them.
  • ARTIFACT fields cannot be filtered.

Handle rate limits and retries

The Records API is rate-limited (API rate limits); record and query limits are separate. On 429, back off exponentially with jitter and a max attempts cap.

Retry safety:

  • POST /records is not idempotent — a retry after a timeout or connection drop can create a duplicate. Dedupe on a natural key, or verify with a follow-up read before retrying.
  • PUT and DELETE /records/{id} and POST /records/query are safe to retry.

Use test_mode for test data

Pass test_mode: true on writes from staging or test workflows. Test records are excluded from live listings and aggregations unless you pass test_mode=true on List or Query.

Attaching records to cases from the record side

  • On Create: case_ids: [<id>, ...] (max 5).
  • On Update: add_case_ids / remove_case_ids (max 5).

For status, comments, fields, or Cases-only reads, use the Cases API.

Configure retention explicitly

Set ttl_days, retention_column_name, max_records_limit, and on_limit_reached at creation time (see Create record type):

  • Enrichment cache: retention_column_name: "UPDATED_AT", on_limit_reached: "EVICT_OLDEST".
  • Audit trail: retention_column_name: "CREATED_AT", on_limit_reached: "REJECT".

Common errors

Status Typical cause
400 Malformed request — filters not valid JSON, unknown field, disallowed operator.
404 Record, type, or field not found — or the token can't see it. Under-privileged tokens return 404, not 403.
422 Validation failure — TEXT_ENUM value not in fixed_values, updating a record whose record type isn't editable, circular parent.
429 Rate limited — back off.
504 Query API exceeded 30s — narrow filters or time range.

Treat 404 on a resource you expect to exist as a scope check on the API key.

Was this helpful?