Data Models
Every Sent API v3 response uses the same JSON envelope. This page documents the shared structures: the response envelope, its error and metadata objects, and the pagination metadata returned by list endpoints. Request and response schemas for individual resources are generated from the OpenAPI specification and rendered on each endpoint page. See Resource schemas.
Naming Convention: The API v3 uses snake_case for all JSON property names (for example, phone_number, created_at).
Response Envelope
All v3 endpoints return the standard ApiResponse envelope:
| Field | Type | Description |
|---|---|---|
success | boolean | true when the request succeeded, false when it failed |
data | object | The response data. Omitted from error responses |
error | ApiError | Error details. Omitted from successful responses |
meta | ApiMeta | Metadata about the request and response |
Example Success Response
{
"success": true,
"data": {
"id": "0b9df168-9917-4b1e-bc5d-9cee5d2ce2d2",
"phone_number": "+15551234567",
"created_at": "2026-01-15T10:30:00Z"
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-01-15T10:30:00Z",
"version": "v3"
}
}Example Error Response
{
"success": false,
"status": 404,
"error": {
"code": "RESOURCE_001",
"message": "Contact not found",
"doc_url": "https://docs.sent.dm/reference/api/error-catalog"
},
"meta": {
"request_id": "req_def456",
"timestamp": "2026-01-15T10:30:00Z",
"version": "v3"
}
}Error Handling documents HTTP status codes and error response semantics; the Error Catalog enumerates every error code with causes and remediation.
ApiError
| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code (for example, RESOURCE_001) |
message | string | Human-readable error message |
details | object | Field-level validation errors: a map of field name to an array of error messages. Omitted when unset |
doc_url | string | URL to documentation about this error. Omitted when unset |
ApiMeta
| Field | Type | Description |
|---|---|---|
request_id | string | Unique identifier for this request, for tracing and support |
timestamp | string (date-time) | Server timestamp when the response was generated |
version | string | API version used for this request (v3) |
Paginated List Responses
Paginated list endpoints return the items array and a pagination object inside data. The array property is named after the resource:
| Endpoint | Array property |
|---|---|
GET /v3/contacts | contacts |
GET /v3/templates | templates |
GET /v3/webhooks | webhooks |
GET /v3/webhooks/{id}/events | events |
GET /v3/conversations | messages |
GET /v3/conversations/{id} | messages |
GET /v3/calls | calls |
Paginated endpoints accept the page query parameter (1-indexed, default 1) and the page_size query parameter (default 20, range 1–100).
Example Paginated Response
{
"success": true,
"data": {
"contacts": [
{
"id": "0b9df168-9917-4b1e-bc5d-9cee5d2ce2d2",
"phone_number": "+15551234567"
}
],
"pagination": {
"page": 1,
"page_size": 20,
"total_count": 42,
"total_pages": 3,
"has_more": true,
"cursors": null
}
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-01-15T10:30:00Z",
"version": "v3"
}
}PaginationMeta
| Field | Type | Description |
|---|---|---|
page | integer | Current page number (1-indexed) |
page_size | integer | Number of items per page |
total_count | integer | Total number of items across all pages |
total_pages | integer | Total number of pages |
has_more | boolean | Whether there are more pages after this one |
cursors | PaginationCursors | null | Optional cursor pagination pointers. null when the response is paginated by page number only |
PaginationCursors
| Field | Type | Description |
|---|---|---|
after | string | null | Cursor to fetch the next page |
before | string | null | Cursor to fetch the previous page |
Resource Schemas
Request and response schemas for each resource are generated from the OpenAPI specification and rendered on the endpoint pages. Each mutation endpoint page documents its own request body; the pages below document the full response model for each resource:
| Resource | Response model | Documented on |
|---|---|---|
| Contacts | ContactResponse | Get contact by ID |
| Messages | MessageResponse | Get message status |
| Templates | TemplateResponse | Get template by ID |
| Profiles | ProfileDetailResponse | Get profile by ID |
| Webhooks | WebhookV3Response | Get a webhook |
| Brand campaigns | BrandCampaignV3Response | Get campaigns for a profile's brand |
| Users | UserResponse | Get user by ID |
| Account | AccountResponse | Get authenticated account |
| Number lookup | NumberLookupResultResponse | Get phone number details |
Message Status Values
The generated schema types the status field on MessageResponse as a plain string, so the endpoint page does not enumerate its values.
QUEUED, ROUTED, SENT, DELIVERED, READ, and FAILED cover the outbound lifecycle, and RECEIVED marks an inbound message from a contact. Four more statuses describe a send that was held, called off, or suppressed:
SCHEDULED: the send is held for a future instant, either ascheduled_atyou set or the end of the recipient's quiet hours. Sent releases the message automatically once that instant arrives and it continues through the normal send path, soSCHEDULEDis not terminal.CANCELLED: you called a held send off withPOST /v3/messages/{id}/cancelbefore it was released. Reachable only fromSCHEDULED, terminal, and never sent. See Cancelling scheduled messages.FILTERED: a policy gate suppressed the send before any provider call, either because the recipient opted out or is on your phone-channel suppression list, or because your routing rules denied it.BLOCKED: an account-level precondition stopped the send before policy evaluation, for example an insufficient balance, an unmet onboarding entitlement, or a template that is not approved for sending.
FILTERED, BLOCKED, and CANCELLED are policy or customer outcomes rather than delivery failures, so all three are excluded from your deliverability rate. Only FAILED counts against it.
A message that is or was held reports its instant in scheduled_at, which GET /v3/messages/{id} returns alongside the base MessageResponse fields, and which message.scheduled and message.cancelled also carry. On a CANCELLED message it is the instant that was called off.
Each of the preceding statuses has a matching webhook sub-type. PROCESSED, which a message reports for the short interval between acceptance and routing, is the one status without a sub-type, so status webhooks never carry it. See Event Types for the full status catalog and the payload shape of each event.