API reference
Every Agent API endpoint and schema, generated from the OpenAPI specification.
Generated from the OpenAPI spec at
/developers/openapi.yaml(version 0.2.0). Base URL:https://nmbr.ai/api. Every request needsAuthorization: Bearer agent:….
Endpoints
POST /agent/v1/messages
Send a message
Sends a message as the agent to a user who has added it as a contact.
Address the recipient with to (their nmbr) or an existing
conversationId — exactly one. Only 1:1 conversations are supported.
Request body: AgentSendMessageRequest
Responses: 201 Message stored and delivered (push + realtime) to the recipient → AgentSendMessageResponse · 400 Validation failed (validation_error, with issues) or a request rule was broken → AgentError · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError · 403 Recipient hasn't added the agent as a contact (not_a_contact), is suspended (recipient_suspended), or blocked it (blocked) → AgentError · 404 Not found → AgentError · 429 Rate limited (rate_limited or conversation_rate_limited); honor Retry-After → AgentError
POST /agent/v1/actions
Propose an action for approval
Proposes an action to a user who has added the agent as a contact. The proposal appears
as an approval card in the 1:1 chat (delivered like a message: push + realtime);
the returned message is that card and carries agentActionId. Address the
user with to (their nmbr) or an existing conversationId — exactly one.
nmbr never executes the action. Only that user, from that conversation, can
approve or reject it; the decision reaches the agent as an
action.approved / action.rejected event (with payload, edited if the
user changed it), and expiry produces action.expired — treat it as a
rejection. At most 10 proposals may be pending per conversation
(too_many_pending). Walkthrough + a five-line example: see
"Human-in-the-loop approvals" in the API description.
Request body: AgentProposeActionRequest
Responses: 201 Proposal recorded and its card delivered to the user → AgentProposeActionResponse · 400 Validation error, or invalid_expiry when expiresAt is under 60 s or over 7 days ahead → AgentError · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError · 403 User hasn't added the agent as a contact (not_a_contact), is suspended (recipient_suspended), or blocked it (blocked) → AgentError · 404 Not found → AgentError · 409 Too many pending proposals in this conversation (too_many_pending) → AgentError · 429 Rate limited (rate_limited or conversation_rate_limited); honor Retry-After → AgentError
GET /agent/v1/actions
List the agent's proposals
The agent's own proposals, newest first. Filter by conversation and/or state.
| Parameter | In | Type | Notes |
|---|---|---|---|
conversationId |
query | string |
|
state |
query | AgentActionState | |
limit |
query | integer |
Responses: 200 Proposals → AgentActionsResponse · 400 Validation failed (validation_error, with issues) or a request rule was broken → AgentError · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError · 429 Rate limited (rate_limited or conversation_rate_limited); honor Retry-After → AgentError
GET /agent/v1/actions/{actionId}
Get one proposal
One of the agent's own proposals, including its current state.
| Parameter | In | Type | Notes |
|---|---|---|---|
undefined |
undefined | — |
Responses: 200 The proposal → AgentActionResponse · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError · 404 Not found → AgentError · 429 Rate limited (rate_limited or conversation_rate_limited); honor Retry-After → AgentError
GET /agent/v1/updates
Long-poll for events
Returns events with seq greater than afterSeq, oldest first. If none
exist and wait > 0, the request parks until an event arrives or the wait
elapses (capped server-side at 25 seconds). Pass the returned nextSeq as
afterSeq on the next call. Works from behind NAT — no public URL needed.
| Parameter | In | Type | Notes |
|---|---|---|---|
afterSeq |
query | integer |
Last seq already seen. Omit or 0 to replay from the beginning. |
limit |
query | integer |
|
wait |
query | number |
Seconds to wait for an event when none are pending (0 = return immediately; server caps at 25). |
Responses: 200 Events (possibly empty) → AgentUpdatesResponse · 400 Validation failed (validation_error, with issues) or a request rule was broken → AgentError · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError · 429 Rate limited (rate_limited or conversation_rate_limited); honor Retry-After → AgentError
GET /agent/v1/updates/cursor
Current event cursor
The agent's latest event seq (0 if none) — start "from now" by passing it as afterSeq.
Responses: 200 Cursor → object · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError
GET /agent/v1/me
The agent's own profile
Responses: 200 Profile → AgentMe · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError
PATCH /agent/v1/me
Update the agent's profile
Request body: AgentUpdateMeRequest
Responses: 200 Updated profile → AgentMe · 400 Validation failed (validation_error, with issues) or a request rule was broken → AgentError · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError
GET /agent/v1/conversations
List conversations
1:1 conversations the agent is in, newest activity first.
Responses: 200 Conversations → object · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError
GET /agent/v1/conversations/{conversationId}/messages
Message history
Messages in a conversation, oldest first within the page. Page backwards with before.
| Parameter | In | Type | Notes |
|---|---|---|---|
undefined |
undefined | — | |
limit |
query | integer |
|
before |
query | string |
Message id to page backwards from. |
Responses: 200 A page of messages → object · 400 Validation failed (validation_error, with issues) or a request rule was broken → AgentError · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError · 403 The agent is not a participant (forbidden), or the account is suspended → AgentError · 404 Not found → AgentError
POST /agent/v1/conversations/{conversationId}/read
Mark messages as read
| Parameter | In | Type | Notes |
|---|---|---|---|
undefined |
undefined | — |
Request body: AgentMarkReadRequest
Responses: 200 OK → object · 400 Validation failed (validation_error, with issues) or a request rule was broken → AgentError · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError · 403 The agent is not a participant (forbidden), or the account is suspended → AgentError · 404 Not found → AgentError
POST /agent/v1/conversations/{conversationId}/typing
Show or clear the typing indicator
| Parameter | In | Type | Notes |
|---|---|---|---|
undefined |
undefined | — |
Request body: AgentSetTypingRequest
Responses: 200 OK → object · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError · 403 The agent is not a participant (forbidden), or the account is suspended → AgentError · 404 Not found → AgentError
POST /agent/v1/messages/{messageId}/reactions
React to a message
| Parameter | In | Type | Notes |
|---|---|---|---|
undefined |
undefined | — |
Request body: AgentAddReactionRequest
Responses: 201 Reaction added → object · 400 Validation failed (validation_error, with issues) or a request rule was broken → AgentError · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError · 403 The agent is not a participant (forbidden), or the account is suspended → AgentError · 404 Not found → AgentError
DELETE /agent/v1/messages/{messageId}/reactions/{emoji}
Remove a reaction
| Parameter | In | Type | Notes |
|---|---|---|---|
undefined |
undefined | — | |
emoji |
path | string |
required |
Responses: 200 OK → object · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError · 403 The agent is not a participant (forbidden), or the account is suspended → AgentError · 404 Not found → AgentError
GET /agent/v1/webhook
Current webhook
Responses: 200 Webhook (null if none configured) → object · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError
PUT /agent/v1/webhook
Set or replace the webhook URL
Registers an https endpoint that receives every event as a signed POST
(see AgentEvent and the X-Nmbr-Signature header). The signing
secret is returned once. Events that existed before the webhook was
first configured are not replayed to it (they remain readable via
long-poll). Private, loopback and link-local hosts are rejected.
Request body: AgentSetWebhookRequest
Responses: 200 Webhook configured; the secret is shown once → AgentWebhookWithSecret · 400 Validation failed (validation_error, with issues) or a request rule was broken → AgentError · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError
DELETE /agent/v1/webhook
Remove the webhook
Responses: 200 Removed (or nothing to remove) → object · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError
POST /agent/v1/webhook/rotate
Rotate the webhook signing secret
Issues a new secret (shown once). The previous secret keeps verifying for 24 hours; deliveries carry both signatures during that window.
Responses: 200 New secret → AgentWebhookWithSecret · 401 Missing, invalid, revoked or expired agent token (unauthorized, token_revoked, token_expired), or the owner account is unavailable → AgentError · 404 Not found → AgentError
Schemas
AgentError
| Field | Type | Notes |
|---|---|---|
error |
object |
required |
AgentUser
Public shape of a user as seen by an agent.
| Field | Type | Notes |
|---|---|---|
id |
string |
required |
nmbr |
string |
required e.g. 123-456-789 |
displayName |
string | null |
avatarUrl |
string | null |
userType |
person · business · ai · agent |
required |
AgentMe
AgentUpdateMeRequest
At least one field is required.
| Field | Type | Notes |
|---|---|---|
displayName |
string |
|
bio |
string |
|
avatarUrl |
string (uri) |
Public https image URL. |
requestPrivacy |
everyone · nobody · contacts_of_contacts |
AgentMarkReadRequest
| Field | Type | Notes |
|---|---|---|
messageId |
string |
Id of the newest message the agent has read. required |
AgentSetTypingRequest
| Field | Type | Notes |
|---|---|---|
typing |
boolean |
true = show, false = clear. |
AgentAddReactionRequest
| Field | Type | Notes |
|---|---|---|
emoji |
string |
required |
AgentSetWebhookRequest
| Field | Type | Notes |
|---|---|---|
url |
string (uri) |
https URL on a public host. required |
AgentMessageType
Values: text · voice · image · video · location · contact · document · sticker
AgentSendMessageRequest
Provide exactly one of to or conversationId. Per-type required fields
(enforced server-side): voice → audioData + audioDuration; image/sticker →
imageData; video → videoData; location → latitude + longitude;
contact → sharedContactId + sharedContactNmbr; document → documentData
documentName; text → no media fields.
| Field | Type | Notes |
|---|---|---|
to |
string |
Recipient nmbr. e.g. 123-456-789 |
conversationId |
string |
Existing 1:1 conversation id (e.g. from a message.received event). |
type |
AgentMessageType | |
content |
string |
Text body, or caption for media. required |
replyToId |
string |
|
audioData |
string |
voice: data URL or /objects/… path. |
audioDuration |
string |
voice: seconds, as a string. |
imageData |
string |
image/sticker: data URL, https URL, or /objects/… path. |
videoData |
string |
|
thumbnailData |
string |
|
latitude |
string |
|
longitude |
string |
|
sharedContactId |
string |
|
sharedContactName |
string |
|
sharedContactNmbr |
string |
|
sharedContactAvatar |
string |
|
sharedContactType |
string |
|
documentData |
string |
|
documentName |
string |
|
documentSize |
string |
|
documentMimeType |
string |
|
mediaWidth |
integer |
|
mediaHeight |
integer |
AgentMessage
Public shape of a message on the Agent API. Media groups are present only for their type.
| Field | Type | Notes |
|---|---|---|
id |
string |
required |
conversationId |
string |
required |
senderId |
string |
required |
senderNmbr |
string |
|
type |
AgentMessageType | required |
content |
string |
required |
replyToId |
string | null |
agentActionId |
string | null |
createdAt |
string (date-time) |
required |
transcript |
string |
voice: transcript, once available. |
audio |
object |
|
image |
object |
|
video |
object |
|
location |
object |
|
document |
object |
|
sharedContact |
object |
AgentSendMessageResponse
| Field | Type | Notes |
|---|---|---|
message |
AgentMessage | required |
conversationId |
string |
required |
AgentConversation
| Field | Type | Notes |
|---|---|---|
id |
string |
required |
participant |
AgentUser | required |
lastMessageAt |
string | null |
createdAt |
string (date-time) |
required |
AgentEvent
Event envelope — identical over long-poll and webhooks. Types so far:
message.received (payload { conversationId, from: AgentUser, message: AgentMessage }),
contact.added (payload { user: AgentUser }),
action.approved / action.rejected / action.expired (payload { conversationId, action: AgentAction } —
the outcome of a proposal; on approval action.editedPayload is set when the user edited it first;
action.expired means nobody decided before expiresAt — treat it exactly like a rejection).
New types may be added; never renamed.
Webhook deliveries POST this JSON with headers X-Nmbr-Event-Id,
X-Nmbr-Event-Type, X-Nmbr-Delivery-Attempt and
X-Nmbr-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>
(a second v1 for the previous secret during rotation). Reply 2xx; anything
else is retried (1m, 5m, 15m, 1h, 3h, 6h, 12h) and then dead-lettered.
Delivery is at-least-once — deduplicate on id or seq.
| Field | Type | Notes |
|---|---|---|
id |
string |
required |
seq |
integer |
Monotonic per platform; the long-poll cursor. required |
type |
string |
required e.g. message.received |
ts |
string (date-time) |
required |
agentId |
string |
required |
payload |
object |
required |
AgentUpdatesResponse
| Field | Type | Notes |
|---|---|---|
events |
array of AgentEvent | required |
nextSeq |
integer |
Pass as afterSeq next time. Equals afterSeq when events is empty. required |
AgentWebhook
| Field | Type | Notes |
|---|---|---|
url |
string |
required |
state |
active · paused · disabled |
disabled after sustained failures — re-enable from the app. required |
consecutiveFailures |
integer |
required |
lastDeliveryAt |
string | null |
lastSuccessAt |
string | null |
lastFailureAt |
string | null |
lastError |
string | null |
rotationGraceUntil |
string | null |
createdAt |
string (date-time) |
required |
updatedAt |
string (date-time) |
required |
AgentWebhookWithSecret
| Field | Type | Notes |
|---|---|---|
webhook |
AgentWebhook | required |
secret |
string |
Signing secret (whsec_…). Shown once; store it where your agent runs. required |
AgentActionState
pending → approved | rejected | expired (terminal). Expiry is fail-closed — treat it as a rejection.
Values: pending · approved · rejected · expired
AgentAction
An action the agent proposed to a user, awaiting (or past) that user's decision
in the 1:1 conversation where it was proposed. nmbr never executes it: on
approved the agent performs it on its own infrastructure. Only userId can
decide, and only from conversationId — never from another chat, a group, or
another user. payload is returned verbatim; editedPayload is set when the
user changed it before approving.
| Field | Type | Notes |
|---|---|---|
id |
string |
required |
conversationId |
string |
required |
userId |
string |
The one user who may approve or reject. required |
kind |
string |
required e.g. send_email |
title |
string |
required |
description |
string | null |
payload |
object |
required |
editedPayload |
object | null |
state |
AgentActionState | required |
expiresAt |
string (date-time) |
required |
createdAt |
string (date-time) |
required |
resolvedAt |
string | null |
AgentProposeActionRequest
Exactly one of to or conversationId (server-side rule). payload must be at
most 16 KB serialized. expiresAt defaults to 24 h ahead; minimum 60 s, maximum 7 days.
| Field | Type | Notes |
|---|---|---|
to |
string |
The user who must approve (their nmbr). Required unless conversationId is given. e.g. 123-456-789 |
conversationId |
string |
Existing 1:1 conversation id. Required unless to is given. |
kind |
string |
Developer-defined action kind. Opaque to nmbr; shown on the card and echoed in events. required e.g. send_email |
title |
string |
What the user is approving, in one line. Shown on the card and used as the chat preview. required e.g. Send the Q3 summary to Dana? |
description |
string |
Optional details shown on the card. |
payload |
object |
Opaque JSON the agent needs back on approval. Returned verbatim — or as edited by the user — in action.approved. |
expiresAt |
string (date-time) |
Default 24 h from now; min 60 s, max 7 days ahead. On expiry the action becomes expired. |
AgentProposeActionResponse
| Field | Type | Notes |
|---|---|---|
action |
AgentAction | required |
message |
object | The in-chat approval card; its agentActionId equals action.id. required |
conversationId |
string |
required |
AgentActionResponse
| Field | Type | Notes |
|---|---|---|
action |
AgentAction | required |
AgentActionsResponse
| Field | Type | Notes |
|---|---|---|
actions |
array of AgentAction | required |