Skip to content
RelationsAI
API fundamentals

Data types

The API uses a few consistent formats. This page specifies them so you can parse and store values correctly.

Identifiers

Ids are strings with a type prefix, at most 64 characters, made of letters, digits, _ and - (URL-safe). They are case sensitive.

PrefixObjectPrefixObject
ws_Workspacercp_Campaign recipient
key_API keyct_Contact
agent_Agentdnc_Do-not-call entry
pn_Phone numberwe_Webhook endpoint
call_Callevt_Event
cmp_Campaignwd_Webhook delivery
req_Request (the X-Request-Id header)
  • Treat ids as opaque. Store them as strings (up to 64 characters); do not parse them, derive meaning from them or build them yourself.
  • An id that is malformed, has the wrong prefix for the path, belongs to another workspace or to the other mode answers resource_not_found: the same answer as an id that never existed.
  • Ids are unique within their type. Keep the mode next to stored ids: a test-mode id means nothing to a live key.

Timestamps

RFC 3339 in UTC with milliseconds, always ending in Z:

Text
2026-10-21T09:30:00.000Z

Send UTC timestamps in filters such as created_after. Durations are plain integers with the unit in the name: duration_seconds on a call, start_ms and end_ms (milliseconds from the start of the call) on transcript turns. Time zones appear as IANA names such as Asia/Kolkata: the workspace's timezone, and details.timezone of outside_calling_hours, which is the zone the calling window was evaluated in. Timestamps themselves are always UTC.

Money

Amounts are objects with an integer in the currency's minor unit and an ISO 4217 code:

JSONJSON
{ "amount": 1250, "currency": "INR" }
  • For INR the minor unit is the paisa: 1250 is ₹12.50. Never use floating-point numbers for amounts.
  • Amounts in responses (a call's cost, a campaign's spend) are what your workspace is charged, never negative, and always 0 in test mode.
  • Amounts you send (a campaign's budget_cap) must be at least 1 and in your workspace's currency, today INR.
  • currency is an open value: today always INR, matching the workspace currency.

A call's cost is null until it is known and final once the call is settled.

Phone numbers

E.164 strings: a +, the country code and the number, digits only, 8 to 15 digits in total:

Text
+12025550100 +12025550150

(Both are fictional test numbers. Use fictional numbers in your own tests and fixtures too.)

  • An invalid number in a request answers invalid_phone_number (400).
  • Remember to URL-encode the + as %2B in query strings (see Filtering).
  • Numbers are returned in full, as stored, to the workspace that owns them.
  • The do-not-call check and the contact lookups match numbers ignoring formatting.

Booleans and null

Booleans are JSON true and false; in query strings, true and false. Every documented field is present in every response; a value that is not set or not known yet is null (for example outcome before a call ends).

Metadata

Calls accept metadata, your own key-value data stored with the object and returned as sent:

  • Up to 16 keys; keys up to 40 characters of letters, digits, _, - and .; values are strings up to 500 characters.
  • Never sent to the person called and never used by the agent.
  • Do not put secrets or sensitive personal data in it. Use it for your own ids ({"crm_lead_id": "L-20931"}), so you can match calls, events and webhook payloads back to your records.

Variables and custom fields

  • Call variables (variables on POST /v1/calls): values the agent can use in the conversation. Up to 50 keys; keys are lowercase letters, digits and _, starting with a letter, up to 64 characters; values are strings up to 500 characters.
  • Custom fields on contacts (custom_fields): values for fields defined in the console. An unknown field name answers custom_field_not_found. Values are strings up to 500 characters; on update, null clears a field and omitted fields are left unchanged.

Enums

Enum values are lowercase snake_case strings: call status, outcome and end_reason, campaign and recipient status, artifact state, readiness reason code, delivery status and so on.

Enums are open: new values can be added at any time without a new API version. Your code must:

  • accept values it does not know, instead of failing to parse the response;
  • treat an unknown value as "other", never as success (an unknown call outcome is not completed);
  • log unknown values so you notice them and can update your handling.

Several enums include unknown today, meaning RelationsAI could not determine the value. It is never a success.