{"openapi":"3.1.0","info":{"title":"Inbound CX API","version":"1","summary":"Calls, contacts and text messages for one organization, behind an API key.","description":"Within v1, fields are added and never removed or renamed. New optional query parameters, new response fields and new endpoints may appear at any time; a client must ignore fields it does not know. Anything that would remove or rename a field ships as v2 at a new path.\n\nAuthenticate with `Authorization: Bearer rk_live_…`. A key is issued in the portal (Settings, API keys) with a chosen subset of the scopes listed under `x-scopes`; `GET /me` reads back the scopes a key actually holds. Every response is JSON. Timestamps are ISO 8601 in UTC. Phone numbers are E.164.\n\nDeliberately absent from v1: live call control, recordings, voicemail, users, roles, billing, phone numbers and call flows. Each is a decision, not a gap: control needs a realtime channel this API does not have, recordings are the most sensitive audio we hold, and the rest change the account, which a leaked key must not be able to do.","contact":{"name":"Inbound CX","url":"https://inboundcx.com","email":"sales@inboundcx.com"}},"servers":[{"url":"https://api.inboundcx.com/api/v1"}],"security":[{"apiKey":[]}],"x-scopes":{"calls.view.team":{"access":"read"},"contacts.view":{"access":"read"},"contacts.manage":{"access":"write"},"sms.view":{"access":"read"},"sms.send":{"access":"write"}},"x-rate-limits":{"perKey":{"requestsPerMinute":120,"keyedOn":"ApiKey.id"},"preAuthentication":{"requestsPerMinute":600,"keyedOn":"client network (IPv6 /64)"}},"tags":[{"name":"Discovery","description":"What this key is and what it may do."},{"name":"Calls","description":"Completed and in-progress calls, read-only."},{"name":"Contacts","description":"The organization's shared directory."},{"name":"Messages","description":"Text conversations, grouped by external number."}],"paths":{"/openapi.json":{"get":{"operationId":"getOpenApi","summary":"This document","description":"Unauthenticated. Rate limited per client network like every request made before a key is checked.","security":[],"responses":{"200":{"description":"The OpenAPI 3.1 document.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/me":{"get":{"operationId":"getMe","summary":"Who this key is, and what it may do","description":"The call an integration makes first to check its credential. Requires a valid key and nothing more: it describes the credential itself, not any tenant data, so it has no scope.","responses":{"200":{"description":"The key, its organization and its effective scopes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"description":"Missing, revoked, expired or unknown API key. `WWW-Authenticate: Bearer` is set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but does not hold the scope this operation requires, or the organization's plan does not include API access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited: 120 requests per minute per key, or 600 per minute per client network before authentication. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are set on every response."}}}},"/calls":{"get":{"operationId":"listCalls","summary":"List calls, newest first","parameters":[{"name":"limit","in":"query","required":false,"description":"Page size. Clamped to 100.","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"The `nextCursor` from the previous page.","schema":{"type":"string","format":"uuid"}},{"name":"direction","in":"query","required":false,"schema":{"type":"string","enum":["inbound","outbound"]}},{"name":"since","in":"query","required":false,"description":"Only calls that started at or after this instant (ISO 8601).","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"One page. `nextCursor` is null on the last page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallList"}}}},"400":{"description":"A field failed validation. `error` names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, revoked, expired or unknown API key. `WWW-Authenticate: Bearer` is set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but does not hold the scope this operation requires, or the organization's plan does not include API access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited: 120 requests per minute per key, or 600 per minute per client network before authentication. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are set on every response."}},"x-required-scope":"calls.view.team"}},"/calls/{id}":{"get":{"operationId":"getCall","summary":"One call by Inbound CX id","description":"The id the list returns. Not the Twilio CallSid, which means different things on the inbound and outbound legs.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallEnvelope"}}}},"401":{"description":"Missing, revoked, expired or unknown API key. `WWW-Authenticate: Bearer` is set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but does not hold the scope this operation requires, or the organization's plan does not include API access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such row in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited: 120 requests per minute per key, or 600 per minute per client network before authentication. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are set on every response."}},"x-required-scope":"calls.view.team"}},"/contacts":{"get":{"operationId":"listContacts","summary":"List contacts","description":"There is no `favoritesOnly`: favourites are per agent and an API key has no agent, so the parameter could only return an empty list.","parameters":[{"name":"limit","in":"query","required":false,"description":"Page size. Clamped to 100.","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"The `nextCursor` from the previous page.","schema":{"type":"string","format":"uuid"}},{"name":"search","in":"query","required":false,"description":"Matches display name, company or number.","schema":{"type":"string","minLength":1,"maxLength":200}},{"name":"includeAutoCreated","in":"query","required":false,"description":"Whether numbers the system created from call history are included. Default true.","schema":{"default":"true","type":"string","enum":["true","false"]}}],"responses":{"200":{"description":"One page. `isFavorite` is not present: it is a per-agent value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactList"}}}},"400":{"description":"A field failed validation. `error` names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, revoked, expired or unknown API key. `WWW-Authenticate: Bearer` is set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but does not hold the scope this operation requires, or the organization's plan does not include API access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited: 120 requests per minute per key, or 600 per minute per client network before authentication. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are set on every response."}},"x-required-scope":"contacts.view"},"post":{"operationId":"createContact","summary":"Create a contact","description":"If the organization already has an auto-created contact for this number (every number ever seen on a call), that row is adopted and named rather than duplicated: the response is 200 with `adopted: true`. A new row is 201.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"maxLength":200},"phoneNumber":{"type":"string","pattern":"^\\+[1-9]\\d{6,14}$","description":"E.164, e.g. +14155550123."},"company":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"tag":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]}},"required":["displayName","phoneNumber"]}}}},"responses":{"200":{"description":"An existing auto-created contact was adopted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactCreated"}}}},"201":{"description":"Created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactCreated"}}}},"400":{"description":"A field failed validation. `error` names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, revoked, expired or unknown API key. `WWW-Authenticate: Bearer` is set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but does not hold the scope this operation requires, or the organization's plan does not include API access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another named contact already has this number. `contactId` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited: 120 requests per minute per key, or 600 per minute per client network before authentication. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are set on every response."}},"x-required-scope":"contacts.manage"}},"/contacts/{id}":{"get":{"operationId":"getContact","summary":"One contact","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactEnvelope"}}}},"401":{"description":"Missing, revoked, expired or unknown API key. `WWW-Authenticate: Bearer` is set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but does not hold the scope this operation requires, or the organization's plan does not include API access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such row in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited: 120 requests per minute per key, or 600 per minute per client network before authentication. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are set on every response."}},"x-required-scope":"contacts.view"},"patch":{"operationId":"updateContact","summary":"Update a contact","description":"Any subset of the create fields. An empty body is refused so a typo'd field name cannot look like success.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"description":"At least one field.","content":{"application/json":{"schema":{"type":"object","properties":{"displayName":{"type":"string","minLength":1,"maxLength":200},"phoneNumber":{"type":"string","pattern":"^\\+[1-9]\\d{6,14}$","description":"E.164, e.g. +14155550123."},"company":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}]},"tag":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}]},"notes":{"anyOf":[{"type":"string","maxLength":5000},{"type":"null"}]}}}}}},"responses":{"200":{"description":"The updated contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactEnvelope"}}}},"400":{"description":"A field failed validation. `error` names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, revoked, expired or unknown API key. `WWW-Authenticate: Bearer` is set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but does not hold the scope this operation requires, or the organization's plan does not include API access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such row in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another contact already uses this phone number. `contactId` says which.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited: 120 requests per minute per key, or 600 per minute per client network before authentication. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are set on every response."}},"x-required-scope":"contacts.manage"},"delete":{"operationId":"deleteContact","summary":"Delete a contact","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"204":{"description":"Deleted."},"401":{"description":"Missing, revoked, expired or unknown API key. `WWW-Authenticate: Bearer` is set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but does not hold the scope this operation requires, or the organization's plan does not include API access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such row in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited: 120 requests per minute per key, or 600 per minute per client network before authentication. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are set on every response."}},"x-required-scope":"contacts.manage"}},"/messages":{"get":{"operationId":"listThreads","summary":"List conversations, newest activity first","description":"One row per external number, organization-wide: all of an organization's numbers share one texting identity.","responses":{"200":{"description":"Every thread.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreadList"}}}},"401":{"description":"Missing, revoked, expired or unknown API key. `WWW-Authenticate: Bearer` is set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but does not hold the scope this operation requires, or the organization's plan does not include API access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited: 120 requests per minute per key, or 600 per minute per client network before authentication. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are set on every response."}},"x-required-scope":"sms.view"},"post":{"operationId":"sendMessage","summary":"Send a text message","description":"Sent as the organization, from its SMS-capable number. This bills the organization at its carrier rate, which is one reason the per-key rate limit exists. A number that has opted out (STOP) is refused.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string","pattern":"^\\+[1-9]\\d{6,14}$","description":"E.164, e.g. +14155550123."},"body":{"type":"string","minLength":1,"maxLength":1600}},"required":["to","body"]}}}},"responses":{"201":{"description":"Queued with the carrier.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageEnvelope"}}}},"400":{"description":"A field failed validation. `error` names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, revoked, expired or unknown API key. `WWW-Authenticate: Bearer` is set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The organization's spending limit or billing status does not allow sending.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but does not hold the scope this operation requires, or the organization's plan does not include API access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"No SMS-capable number is configured for the organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited: 120 requests per minute per key, or 600 per minute per client network before authentication. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are set on every response."}},"x-required-scope":"sms.send"}},"/messages/{counterpart}":{"get":{"operationId":"listThreadMessages","summary":"The messages in one conversation","description":"Reading a thread through the API does NOT mark it read: that is a side effect of a person opening it in the softphone.","parameters":[{"name":"counterpart","in":"path","required":true,"description":"The external number, E.164. A literal `+` is legal in a path segment.","schema":{"type":"string","pattern":"^\\+[1-9]\\d{6,14}$"}},{"name":"limit","in":"query","required":false,"description":"Page size. Clamped to 100.","schema":{"default":50,"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","required":false,"description":"The `nextCursor` from the previous page; pages go backwards in time.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"One page, newest first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageList"}}}},"400":{"description":"A field failed validation. `error` names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, revoked, expired or unknown API key. `WWW-Authenticate: Bearer` is set.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is valid but does not hold the scope this operation requires, or the organization's plan does not include API access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited: 120 requests per minute per key, or 600 per minute per client network before authentication. `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` are set on every response."}},"x-required-scope":"sms.view"}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"rk_live_…","description":"An API key issued in the portal, sent as `Authorization: Bearer rk_live_…`. Keys are hashed at rest and shown once at issuance. Scopes are a subset of `x-scopes`, chosen when the key is issued."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"},"code":{"description":"Machine-readable, present on some errors (e.g. `not_found`).","type":"string"}},"required":["error"]},"Me":{"type":"object","properties":{"tenant":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"plan":{"type":"string"}},"required":["id","name","slug","plan"]},{"type":"null"}],"description":"The organization this key belongs to."},"apiKey":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"prefix":{"type":"string","description":"The visible first characters of the key, e.g. `rk_live_8f3a`."},"expiresAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","name","prefix","expiresAt","createdAt"]},{"type":"null"}]},"permissions":{"type":"array","items":{"type":"string","enum":["calls.view.team","contacts.view","contacts.manage","sms.view","sms.send"]},"description":"The scopes this key actually holds, which is what every other endpoint enforces."},"rateLimit":{"type":"object","properties":{"requestsPerMinute":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["requestsPerMinute"]}},"required":["tenant","apiKey","permissions","rateLimit"]},"Call":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Inbound CX's id for the call. Not the Twilio CallSid."},"direction":{"type":"string","enum":["inbound","outbound"]},"fromNumber":{"type":"string"},"toNumber":{"type":"string"},"status":{"type":"string","description":"queued | ringing | in-progress | completed | failed | no-answer, and others as Twilio adds them."},"startedAt":{"type":"string","format":"date-time"},"answeredAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"endedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"durationSec":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}]},"isInternal":{"type":"boolean","description":"True for an extension-to-extension call that never touched the PSTN."},"agentId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]},"contactId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]}},"required":["id","direction","fromNumber","toNumber","status","startedAt","answeredAt","endedAt","durationSec","isInternal","agentId","contactId"]},"CallList":{"type":"object","properties":{"calls":{"type":"array","items":{"$ref":"#/components/schemas/Call"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]}},"required":["calls","nextCursor"]},"CallEnvelope":{"type":"object","properties":{"call":{"$ref":"#/components/schemas/Call"}},"required":["call"]},"Contact":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenantId":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"phoneNumber":{"type":"string","description":"As entered. `normalizedNumber` is the E.164 form."},"company":{"anyOf":[{"type":"string"},{"type":"null"}]},"tag":{"anyOf":[{"type":"string"},{"type":"null"}]},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"createdByAgentId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Null when created through the API or by the system."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"normalizedNumber":{"anyOf":[{"type":"string"},{"type":"null"}]},"isAutoCreated":{"type":"boolean","description":"True when the system created the row from a call rather than a person adding it."},"source":{"type":"string","description":"manual | auto_inbound | auto_outbound"},"consentStatus":{"type":"string","description":"unknown | opted_in | opted_out, as recorded by the messaging consent rules."},"consentSource":{"anyOf":[{"type":"string"},{"type":"null"}]},"consentAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"consentNote":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","tenantId","displayName","phoneNumber","company","tag","notes","createdByAgentId","createdAt","updatedAt","normalizedNumber","isAutoCreated","source","consentStatus","consentSource","consentAt","consentNote"]},"ContactList":{"type":"object","properties":{"contacts":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]}},"required":["contacts","nextCursor"]},"ContactEnvelope":{"type":"object","properties":{"contact":{"$ref":"#/components/schemas/Contact"}},"required":["contact"]},"ContactCreated":{"type":"object","properties":{"contact":{"$ref":"#/components/schemas/Contact"},"adopted":{"type":"boolean","description":"True (with status 200) when an existing auto-created contact for this number was adopted rather than a new row created (201)."}},"required":["contact","adopted"]},"Thread":{"type":"object","properties":{"counterpartNumber":{"type":"string","description":"The external number, E.164. Use it as `:counterpart`."},"lastMessage":{"type":"string"},"lastDirection":{"type":"string","enum":["inbound","outbound"]},"lastStatus":{"type":"string"},"lastAt":{"type":"string","format":"date-time"},"messageCount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"hasUnread":{"type":"boolean"}},"required":["counterpartNumber","lastMessage","lastDirection","lastStatus","lastAt","messageCount","hasUnread"]},"ThreadList":{"type":"object","properties":{"threads":{"type":"array","items":{"$ref":"#/components/schemas/Thread"}}},"required":["threads"]},"Message":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"tenantId":{"type":"string","format":"uuid"},"direction":{"type":"string","enum":["inbound","outbound"]},"fromNumber":{"type":"string"},"toNumber":{"type":"string"},"counterpartNumber":{"type":"string"},"body":{"type":"string"},"status":{"type":"string","description":"queued | sent | delivered | failed | received"},"messageSid":{"type":"string","description":"Twilio's MessageSid."},"agentId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"The sender, outbound only. Null when sent through the API."},"isRead":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","tenantId","direction","fromNumber","toNumber","counterpartNumber","body","status","messageSid","agentId","isRead","createdAt"]},"MessageList":{"type":"object","properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/Message"}},"nextCursor":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}]}},"required":["messages","nextCursor"]},"MessageEnvelope":{"type":"object","properties":{"message":{"$ref":"#/components/schemas/Message"}},"required":["message"]}}}}