Skip to content
Inkbox

Inkbox

DocsPricingBlogContact
GuidesAPI Reference

Ctrl K

GuidesAPI Reference

Jump to

Manage Identities

Agent identities are the unit of presence on Inkbox. Each identity owns exactly one mailbox and one tunnel; you can optionally attach a phone number and vault-secret access. Handles are globally unique across all Inkbox customers and are normalized — a leading @ is automatically stripped, so @my-agent and my-agent are equivalent.


Create identity POST

POST /identities

Atomically provisions the identity, its mailbox, and its tunnel in a single transaction. You can optionally provision and link a phone number, and attach access to existing vault secrets in the same request. The mailbox and tunnel are always created; the nested mailbox and tunnel bodies only customize them.

Request body

FieldTypeRequiredDescription
agent_handlestringYesHandle for the identity. Globally unique. Leading @ is stripped.
display_namestringNoHuman-readable name for the identity. Max 255 chars. Defaults to agent_handle when omitted.
descriptionstring | nullNoFree-form description of what the identity is. Org-internal — never surfaced in outbound email, call audio, or webhook payloads. Defaults to null. Empty string "" is accepted and stored distinctly from null.
imessage_enabledbooleanNoWhether the identity can be reached over iMessage. Defaults to false; set true to opt in.
mailboxobjectNoOptional mailbox-spec. The mailbox is always provisioned; this body only customizes the sending domain or local part.
tunnelobjectNoOptional tunnel-spec. The tunnel is always provisioned; this body only opts into passthrough TLS.
phone_numberobjectNoOptional phone-number provisioning payload. Omit to skip.
vault_secret_idsstring or arrayNoOptional vault secret attachment request. Provide a single secret ID, a list of IDs, or "all" / "*" to attach all active secrets.

mailbox fields

FieldTypeRequiredDescription
email_local_partstringNoCustom local part. Only meaningful when the resolved sending domain is a custom domain — on the platform domain the local part is forced to agent_handle.
sending_domainstring | nullNoBare-domain selector (e.g. "mail.acme.com", not a full email address). Omit to use the org default sending domain; pass null to force the platform domain; pass a string to pin to a verified custom domain.

Sending-domain resolution. Omitting mailbox does not necessarily yield {agent_handle}@inkboxmail.com. The server resolves the sending domain in three cases: if the org has set a verified custom domain as its default, omitting the body lands the mailbox on that custom domain with a server-chosen local part; passing "sending_domain": null forces the platform domain and the local part to agent_handle; passing an explicit bare-domain string pins the mailbox to that verified custom domain (404 if the domain isn't verified for your org).

tunnel fields

FieldTypeRequiredDescription
tls_modestringNo"edge" (default) or "passthrough". Fixed at creation.

The tunnel name is always forced to agent_handle; the public hostname is e.g. my-agent.inkboxwire.com.

phone_number fields

FieldTypeRequiredDescription
typestringNoNumber type to provision: toll_free or local. Defaults to toll_free.
statestringNoOptional US state abbreviation filter. Only supported when type is local.
incoming_call_actionstringNoHow inbound calls are handled: auto_reject, auto_accept, or webhook. Defaults to auto_reject.
client_websocket_urlstringConditionallyRequired when incoming_call_action is auto_accept. Must be a wss:// URL.
incoming_call_webhook_urlstringConditionallyRequired when incoming_call_action is webhook. Must be an https:// URL.

vault_secret_ids

Use this to attach existing vault secret access to the new identity. The organization must already have an active vault. If omitted, no vault secret access is attached.

Accepted forms:

  • A single stringified UUID to attach one secret
  • A list of UUIDs to attach specific secrets
  • "all" or "*" to attach all active secrets in the active vault

Request example

JSONJSON

Response (201)

Returns the full identity-detail shape with nested mailbox and tunnel objects always populated; phone_number is populated when one was provisioned.

JSONJSON

mailbox and tunnel are always populated for active customer identities; only phone_number is optional. If vault_secret_ids is omitted, no vault secret access is attached.

Mailbox local-part validation

When you provide mailbox.email_local_part, it must satisfy these rules:

  • Length: 3–64 characters
  • Characters: lowercase letters, numbers, hyphens (-), underscores (_), and dots (.)
  • Start/end: must begin and end with a letter or number
  • No consecutive dots: my..agent is rejected
  • No @: provide the handle only, not a full email address
  • Reserved names blocked: some system addresses are reserved; you'll get a 409 if you pick one.

Handle validation

Handles are globally unique across all Inkbox customers. They must satisfy:

  • Length: 3–63 characters
  • Characters: lowercase letters (a-z), digits (0-9), and hyphens (-)
  • Start/end: must begin and end with a letter or digit
  • No consecutive hyphens

Some handles are reserved; you'll get a 409 if you pick one.

Error responses

StatusDescription
403Organization ID missing from token
404No active vault exists for the organization, requested vault secrets were not found, the requested sending domain isn't a verified custom domain for your org, or no phone numbers matched the requested criteria
409Handle is already taken — see envelope below
422Request validation failed (e.g. invalid local part, over-long description, unknown field)
429Phone number limit reached for the organization
502Phone number provisioning failed

The 409 body uses a stable error envelope:

JSONJSON

blocking_namespace is a programmatic discriminator with three possible values — "identities", "tunnels", or "mail" — indicating which resource produced the conflict.

Code examples


List identities GET

GET /identities

List all identities for your organization, newest first. Returns the flat identity object — nested mailbox / tunnel / phone_number blocks are not included on list. Use Get identity to fetch the detail shape.

Each identity carries its access rules, so you can see who can view it without a follow-up call. Agent-scoped API keys get a narrowed list — only their own identity plus identities granted to them — and an empty access array.

Response (200)

JSONJSON

Code examples


Get identity GET

GET /identities/{agent_handle}

Get a single identity with its linked communication channels. Returns the identity-detail shape with nested mailbox, tunnel, and (when attached) phone_number objects.

With an agent-scoped API key, only the caller's own identity and identities granted to it via agent visibility are reachable; any other handle returns 404.

Path parameters

ParameterTypeDescription
agent_handlestringHandle of the identity (leading @ is stripped)

Response (200)

JSONJSON

mailbox and tunnel are always populated for active customer identities. phone_number is null when no phone number is attached.

Error responses

StatusDescription
403Organization ID missing from token
404Identity not found

Code examples


Update identity PATCH

PATCH /identities/{agent_handle}

Update an identity's handle, display name, description, iMessage settings, or status. Returns the flat identity object — nested mailbox, tunnel, and phone_number blocks are not included on PATCH responses; use Get identity to fetch the detail shape.

Path parameters

ParameterTypeDescription
agent_handlestringCurrent handle of the identity to update

Request body

FieldTypeRequiredDescription
agent_handlestringNoNew handle. Globally unique. Renaming also renames the linked tunnel in the same transaction. Forbidden when the linked mailbox lives on the platform domain — the handle is the mailbox name there, so a rename would break inbound delivery (returns 409).
display_namestring | nullNoNew display name. Max 255 chars.
descriptionstring | nullNoNew free-form description.
imessage_enabledbooleanNoToggle whether the identity can be reached over iMessage.
imessage_filter_modestringNo"whitelist" or "blacklist" for iMessage contact rules. Requires an admin API key, or manage it from the Inkbox Console.
statusstringNoNew status: "active" or "paused".

PATCH semantics

The server distinguishes three caller intents on display_name and description:

IntentWire payloadResult
Leave unchangedomit the key from the bodyrow untouched
Clear{"<field>": null}column cleared to null
Replace{"<field>": "new text"}column updated

agent_handle, status, imessage_enabled, and imessage_filter_mode accept only the omit half — sending null for those fields is not a clear operation.

Request example

JSONJSON

Response (200)

JSONJSON

Error responses

StatusDescription
403Organization ID missing from token, or imessage_filter_mode sent without an admin API key
404Identity not found
409New handle is already taken, or rename rejected because the linked mailbox lives on the platform domain
422Request validation failed (e.g. invalid status, over-long display name)

The 409 body for a taken handle uses the same envelope as create: { code: "agent_handle_taken", message, blocking_namespace }. The 409 for a platform-domain rename returns a flat { detail: "Cannot rename agent_handle: ..." } body explaining that the handle is the mailbox name on the platform domain.

Code examples


Delete identity DELETE

DELETE /identities/{agent_handle}

Delete an identity. The linked mailbox and tunnel are deleted as part of the cascade. Any identity-scoped API keys tied to this identity are revoked. Any linked phone number is released back to the carrier as part of the cascade — phone numbers cannot exist without an identity. The handle becomes available for reuse immediately. Returns 204 No Content on success.

If the carrier release fails, the entire delete is aborted with a 502 and the identity stays active so you can retry safely.

Path parameters

ParameterTypeDescription
agent_handlestringHandle of the identity to delete

Error responses

StatusDescription
403Organization ID missing from token
404Identity not found
502Carrier release of the linked phone number failed — retry shortly

Code examples


Identity object

FieldTypeDescription
idUUIDUnique identity identifier
organization_idstringOrganization that owns this identity
agent_handlestringGlobally unique handle
display_namestring | nullHuman-readable display name
descriptionstring | nullFree-form description; org-internal
imessage_enabledbooleanWhether the identity can be reached over iMessage. Defaults to false
imessage_filter_modestring"whitelist" or "blacklist" for iMessage contact rules. Defaults to "blacklist"
email_addressstring | nullEmail address of the linked mailbox
has_avatarbooleanWhether a contact-card avatar is stored for this identity
created_atstringCreation timestamp (ISO 8601)
updated_atstringLast update timestamp (ISO 8601)
accessarrayVisibility rules for this identity — who can see it. Populated only on the List identities response, and only for admin callers — empty ([]) on create, get, and update responses, and for agent-scoped callers. To read an identity's rules directly, use the access endpoint.

Identity detail object

Extends the identity object with linked channel data. Returned by the create endpoint and the get endpoint.

FieldTypeDescription
...all identity fields
mailboxobject | nullLinked mailbox object. Always populated for active customer identities.
tunnelobject | nullLinked tunnel object. Always populated for active customer identities.
phone_numberobject | nullLinked phone number object, or null if no phone number is attached

Inkbox

Copyright © 2026 Inkbox

This site is protected by reCAPTCHA.

Google Privacy Policy and Terms of Service apply.

Website

Inkbox

Copyright © 2026 Inkbox

This site is protected by reCAPTCHA.

Google Privacy Policy and Terms of Service apply.

Website

Y CombinatorBacked by Y Combinator
Manage Identities