@inkbox/cli
v0.7.7
Published
CLI for the Inkbox API
Readme
@inkbox/cli
Command-line interface for the Inkbox API — identities, email, phone, and encrypted vault for AI agents.
Install
npm install -g @inkbox/cliOr run directly with npx:
npx @inkbox/cli <command>Requires Node.js >= 22.
Companion mode
Companion mode is off by default, separate from whitelist/blacklist settings. Eligibility requires active exact email/number allow rules covering both directions, either one Both rule or two applicable one-way allows. It is per normalized identifier and channel; phone and iMessage share one policy. Domain allowances, default access, contact visibility, and access borrowed from another Companion conversation do not qualify. Multiple senders may qualify; the first qualifying group message activates the conversation, without repeated initialization when another eligible sender messages. Mere participation is insufficient. Configuration does not add permissions or SMS consent; blocks remain authoritative.
inkbox --json identity companion get example-agent
# Administrator credentials are required for both writes.
inkbox identity mail-rules create example-agent \
--action allow --match-type exact_email --match-target [email protected] --direction both
inkbox --json identity companion update example-agent --enabled true
# [email protected] sends "Please join this conversation" to the group.
inkbox --json identity companion conversations example-agent --channel mail --limit 50 --offset 0
inkbox --json identity companion history example-agent 22222222-2222-4222-8222-222222222222 --limit 100
inkbox --json identity companion history example-agent 22222222-2222-4222-8222-222222222222 --cursor opaque-cursor
inkbox --json identity companion initialization example-agent 22222222-2222-4222-8222-222222222222 --max-bytes 8388608
inkbox --json identity companion update example-agent --enabled falseAdministrator and claimed-agent reads return enabled state, revision, readiness,
and optional notices. Updates require --enabled true|false; unknown options are
rejected. Enabling is allowed before any eligible sender or channel resource
exists. Per-channel readiness reports prerequisites independently of enabled
state, including bidirectional_allow_required when no exact bidirectional allow
exists. Revision changes only when enabled changes; turning off and on requires a
fresh qualifying message. Continued access depends on the actual trigger sender's
permissions and membership, without transferring to another eligible participant.
state aliases conversations. State pages retain items/total, while
history JSON retains historyComplete, nextCursor, replyContext, and notices.
Pages support limits 1-200; conversation offsets are 0-10,000.
initialization loads all pages, deduplicates messages, validates scope and
cursor progress, and revalidates permission before returning one combined
text plus ordered entries and canonical reply context. Default bounds are
8 MiB of fetched-page and transcript UTF-8 bytes and 1,000 pages; use
--max-bytes/--max-pages for your host's capacity. Exceeding a bound fails
before output; it never truncates. For lossless streaming use history pages.
Persist a conversation/activation checkpoint before passing the combined text to a host once. Buffer live traffic until initialization completes, retain reply context per turn, and reconcile uncertain host acceptance on recovery. Historical commands are data, not fresh commands. Replies must use the existing stored mail parent or canonical phone/iMessage conversation, never a private last-sender address. Ordinary-phase events have no activation authority.
Notices keep the normal stderr behavior; --json --with-response-metadata
opts into one stdout envelope. HTTP errors remain nonzero exits with no partial
stdout. Reply readiness remains separate from read access, including existing
SMS consent and dedicated-line group iMessage requirements. MMS chats with the
same participants represent one logical conversation.
Authentication
Set your API key as an environment variable or pass it as a flag:
export INKBOX_API_KEY="ApiKey_..."
export INKBOX_VAULT_KEY="my-vault-key" # only needed for vault decrypt/createGet your API key at inkbox.ai/console.
Quick start
# Create an agent identity (mailbox is created automatically)
inkbox identity create support-bot
# Send an email
inkbox email send -i support-bot \
--to [email protected] \
--subject "Your order has shipped" \
--body-text "Tracking number: 1Z999AA10123456784"
# List recent emails
inkbox email list -i support-bot --limit 10
# List identities visible to this credential (JSON output)
inkbox --json identity listWith --json, successful output is written to stdout. API errors are written as
one JSON object to stderr with error.type, error.message, error.statusCode,
error.detail, error.retryAfterSeconds, and error.agentSupport.
Response notices
Advisory notices are printed to stderr without changing ordinary stdout. With
--json, successful stdout keeps its existing shape and notices appear in one
{"notices": [...]} stderr record. Each notice has string code, level, and
message fields; unfamiliar codes and levels are preserved.
For finite structured commands, opt into a single result document:
inkbox --json --with-response-metadata identity phone-rules list support-botThe result is {"data": <original result>, "notices": [...]}. Notices are omitted
when absent and empty success uses "data": null. Identical notices from internal
lookups or pagination appear once. Errors keep the existing stderr error envelope
and nonzero exit status, with optional top-level notices and unchanged
error.agentSupport guidance.
--with-response-metadata requires --json. Raw certificate stdout from
tunnel sign-csr rejects it before making requests; use --out for a structured
file result. File downloads retain their existing bytes and structured status
output. Notices never authorize an operation or cause a retry.
Directional contact rules
Requires CLI 0.7.3 or later.
All identity mail/phone rules, deprecated mailbox/number rules, and iMessage
contact-rule commands accept --direction inbound|outbound|both on create,
update, and list operations. Inbound is communication from the counterparty to
the agent; outbound is communication from the agent to the counterparty.
inkbox identity update support-bot \
--mail-inbound-filter-mode blacklist --mail-outbound-filter-mode whitelist
inkbox identity mail-rules create support-bot \
--action allow --match-type exact_email --match-target [email protected] \
--direction outbound
inkbox identity mail-rules update support-bot RULE_ID \
--action block --apply-to outboundOmitting create direction means Both; omitting update direction preserves it.
Updates accept action, direction, or both. --apply-to inbound|outbound requires
--action, excludes --direction, and atomically preserves the opposite side.
List filters for inbound/outbound include Both rules; both is exact. A2A's
existing exact-direction behavior is unchanged. Compatible rules can consolidate,
so a successful create may return an existing ID. Trust the returned rule.
Identity update also accepts --phone-inbound-filter-mode and
--phone-outbound-filter-mode. Existing shared mode flags set both directions;
do not combine shared and directional flags for the same channel. Identity
details expose both effective modes. Phone modes also apply to iMessage.
contacts access set --file accepts inboundContactable and
outboundContactable lists inside email/phone groups:
{"email":{"inboundContactable":["[email protected]"],"outboundContactable":[]}}Legacy contactable reads mean outbound; writes still affect both directions.
Omitted lists preserve state and empty lists block current addresses on the named
side. Mixing legacy and directional lists in one group, or supplying null, is
invalid. Communication-policy files also accept address direction and
expectedInboundAction/expectedOutboundAction concurrency checks. A one-way
edit requires only the matching directional guard; Both requires both when
expectedAction is omitted.
contacts permissions set --file also accepts inboundEmails, outboundEmails,
inboundPhones, and outboundPhones boolean maps. Each map may contain up to 50
addresses. Shared emails/phones maps cannot be combined with directional maps
for the same channel, and null is invalid. These maps also work in the initial
permissions of a contacts create --json payload. The alternative initial
permissions.addresses form accepts up to 200 directional decisions, while the
contact remains limited to 50 email and 50 phone identifiers.
Commands
signup
Agent self-signup flow. The create command does not require an API key.
inkbox signup create # Register a new agent (no API key needed)
--human-email <email> # Email of the human to approve (required)
--note-to-human <note> # Message to human in verification email (required)
--display-name <name> # Agent display name (optional)
--agent-handle <handle> # Requested agent handle (optional)
--email-local-part <local> # Requested mailbox local part (optional)
--harness <harness> # Runtime name for matching plugin guidance (optional)
--invitation-prompt # Prompt privately for an invitation link or token
--invitation-stdin # Read an invitation link or token from stdin
# Or set INKBOX_A2A_INVITATION
# Token-named flags/env remain aliases
inkbox signup verify # Submit verification code
--code <code> # 6-digit code from email (required)
inkbox signup resend-verification # Resend the verification email (5-min cooldown)
# Returns current organization_id (may change after verify/approval)
inkbox signup status # Check claim status and restrictionsidentity
Manage agent identities.
inkbox identity list # Agent-scoped credentials return only themselves
inkbox identity get <handle> # Get identity details
inkbox a2a directory # Discover organization peers
inkbox identity create <handle> # Provisions identity + mailbox + tunnel atomically
--display-name <name> # Identity-level display name
--description <text> # Identity-level free-form description
--email-local-part <part> # Requested local part (custom-domain only)
--sending-domain <name> # Bind mailbox to a verified custom domain (bare name)
--platform-domain # Force the platform sending domain (mutually exclusive)
--tls-mode <mode> # edge (default) or passthrough — fixed at create time
--imessage-enabled # Opt the identity into iMessage (default off)
inkbox identity delete <handle> # Cascades to mailbox + tunnel; revokes scoped API keys
inkbox identity update <handle> # Update an identity
--new-handle <handle> # New handle
--display-name <name> # New display name ("" to clear)
--description <text> # New description ("" to clear)
--clear-description # Explicit null (mutually exclusive with --description)
--imessage-enabled <bool> # Toggle iMessage reachability (true/false)
--imessage-filter-mode <mode> # whitelist or blacklist (admin API key required)
inkbox identity refresh <handle> # Re-fetch identity from API
inkbox identity create-secret <handle> # Create a secret scoped to identity (vault key)
--name <name> # Secret name (required)
--type <type> # Secret type (required)
--description <desc> # Optional description
(same secret type flags as vault create)
inkbox identity get-secret <handle> <secret-id> # Decrypt a secret (vault key)
inkbox identity delete-secret <handle> <secret-id> # Delete a secret (vault key)
inkbox identity revoke-access <handle> <secret-id> # Revoke credential access
inkbox identity release-phone <handle> # Release phone number back to the carrier
inkbox identity set-totp <handle> <secret-id> # Add TOTP to login (vault key)
--uri <otpauth-uri> # otpauth:// URI (required)
inkbox identity remove-totp <handle> <secret-id> # Remove TOTP (vault key)
inkbox identity totp-code <handle> <secret-id> # Generate TOTP code (vault key)
Email operations, scoped to an identity. Requires -i <handle>.
inkbox email send -i <handle> # Send an email
--to <addresses> # Comma-separated recipients (required)
--subject <subject> # Email subject (required)
--body-text <text> # Plain text body
--body-html <html> # HTML body
--cc <addresses> # Comma-separated CC
--bcc <addresses> # Comma-separated BCC
--in-reply-to <message-id> # Message ID to reply to
--attach <path> # Attach a file (repeatable)
--inline-image <cid=path> # Embed an image inline as cid:<cid>
# (repeatable; requires --body-html,
# image/*; reference it in the HTML
# as <img src="cid:<cid>">)
--track-opens # Embed an open-tracking pixel
# (requires --body-html)
inkbox email reply-all <message-id> -i <handle> # Reply to everyone on a message
--subject <subject> # Override subject
--body-text <text> # Plain text body
--body-html <html> # HTML body
--reply-to <address> # Reply-To address
--attach <path> # Attach a file (repeatable)
--inline-image <cid=path> # Embed an image inline as cid:<cid>
# (repeatable; requires --body-html)
inkbox email forward <message-id> -i <handle> # Forward a message
--to <addresses> # Comma-separated recipients
--cc <addresses> # Comma-separated CC
--bcc <addresses> # Comma-separated BCC
# (at least one of to/cc/bcc)
--mode <mode> # 'inline' (default) or 'wrapped'
--subject <subject> # Override subject (default: 'Fwd: ...')
--body-text <text> # Plain text caller note
--body-html <html> # HTML caller note
--no-include-original-attachments # Drop originals (inline mode)
--reply-to <address> # Reply-To for the forward
--attach <path> # Attach an additional file (repeatable)
--track-opens # Embed an open-tracking pixel
# (inline forwards reuse the
# original's HTML; server 422s
# if the forward has no HTML)
inkbox email drafts create -i <handle> # Create an incomplete draft; prints generation
--to <addresses> # Optional comma-separated recipients
--subject <subject> # Optional subject
--body-text <text> # Optional plain text body
--attach <path> # Attach a file (repeatable)
--idempotency-key <key> # Reuse with identical args for one logical create
inkbox email drafts list -i <handle> # List drafts with current generations
inkbox email drafts get <draft-id> -i <handle> # Get bodies and attachment metadata
inkbox email drafts update <draft-id> -i <handle> --generation <n>
--subject <subject> # Set a field
--clear-subject # Send explicit null to clear it
--clear-recipients # Clear To, CC, and BCC
inkbox email drafts duplicate <draft-id> -i <handle> --generation <n>
inkbox email drafts delete <draft-id> -i <handle> --generation <n>
inkbox email drafts send <draft-id> -i <handle> --generation <n>
inkbox email drafts attachment add <draft-id> -i <handle> --generation <n> --attach <path>
inkbox email drafts attachment remove <draft-id> <part-index> -i <handle> --generation <n>
inkbox email drafts attachment download <draft-id> <part-index> -i <handle> --generation <n> --output <path>
inkbox email list -i <handle> # List emails
--direction <dir> # Filter: inbound or outbound
--limit <n> # Max messages (default: 50)
inkbox email get <message-id> -i <handle> # Get full message with body
# Fetching an inbound message
# marks it read server-side.
inkbox email search -i <handle> # Search emails
-q, --query <query> # Search query (required)
--limit <n> # Max results (default: 50)
inkbox email unread -i <handle> # List unread emails
--direction <dir> # Filter: inbound or outbound
--limit <n> # Max messages (default: 50)
inkbox email mark-read <ids...> -i <handle> # Mark messages as read
inkbox email mark-unread <ids...> -i <handle> # Mark messages as unread
inkbox email download-attachment <message-id> <filename> -i <handle> # Time-limited download URL
inkbox email delete <message-id> -i <handle> # Delete a message
inkbox email delete-thread <thread-id> -i <handle> # Delete a thread
inkbox email star <message-id> -i <handle> # Star a message
inkbox email unstar <message-id> -i <handle> # Unstar a message
inkbox email thread <thread-id> -i <handle> # Get thread with all messagesUse the generation printed by the latest create, list, get, or mutation
for the next mutation. Attachment part indexes belong to that same generation;
refresh with get after an edit. Drafts share the standard mailbox Drafts
folder, so connected mail clients and the CLI see each other's edits.
A successful drafts send prints the sent message and removes the draft. An
exact-generation retry may return the same sent message. On HTTP 409, refresh
for draft_generation_conflict and retry the same draft ID and generation for
draft_send_in_progress. Do not resend draft_delivery_uncertain; after
checking sent mail, duplicate or delete that draft instead.
phone
Phone operations require -i <handle>, except the organization-scoped
phone hosted-agent voices catalog.
Phone number details from inkbox identity get <handle> and
inkbox identity refresh <handle> include phoneCountry (an ISO 3166-1 alpha-2
code such as US or GB) and phoneState (null when not applicable).
Older phone responses without a country code are reported as US.
inkbox phone call -i <handle> # Place an outbound call
--to <number> # E.164 phone number (required)
--ws-url <url> # WebSocket URL (wss://) for audio bridging
--hosted # Let Inkbox Voice AI drive the call
# (requires --reason; conflicts with --ws-url)
--reason <text> # Voice AI's task brief — what to accomplish
--authority-mode <mode> # Optional contact_scoped or yolo override;
# omit to inherit the saved Voice AI authority
--on-voicemail <action> # leave_message, hang_up, or ignore; omit for the
# default (leave_message with --hosted, else hang_up)
--voicemail-message <text> # What Voice AI says on the voicemail
# (requires --on-voicemail leave_message)
--no-voicemail-detection # Deprecated; same as --on-voicemail ignore
--origination <origin> # dedicated_number (default) or
# shared_imessage_number or
# dedicated_imessage_number
inkbox phone calls -i <handle> # List calls
--limit <n> # Max results (default: 50)
--offset <n> # Pagination offset (default: 0)
# mode / reason / post_call_action_items
# ride each call; read them with --json
inkbox phone hangup <call-id> -i <handle> # Hang up a live call from outside it
inkbox phone transcripts <call-id> -i <handle> # Get call transcripts
inkbox phone tool-activity <call-id> -i <handle> # List paginated Voice AI tool activity
--limit <n> # Max results (default: 50)
--offset <n> # Pagination offset (default: 0)
inkbox phone search-transcripts -i <handle> # Search transcripts
-q, --query <query> # Search query (required)
--party <party> # Filter: local or remote
--limit <n> # Max results (default: 50)
inkbox phone incoming-action [action] -i <handle> # Get (no action) or set the identity's
# incoming-call action: auto_accept,
# auto_reject, webhook, hosted_agent,
# or forward
--ws-url <url> # WebSocket URL (wss://) for audio bridging
--webhook-url <url> # HTTPS receiver for the webhook action
--forward-to-phone <number> # Complete E.164 forwarding target
--forward-to-sip <uri> # SIP target with a public DNS hostname
inkbox phone hosted-agent voices # Organization's voice catalog; no -i needed
inkbox phone hosted-agent voices --json # Complete { voices, defaultVoice } catalog
inkbox phone hosted-agent get -i <handle> # Show the Inkbox Voice AI config
inkbox phone hosted-agent set -i <handle> # Set it — full replace: an omitted flag
# resets that field to the server default
--voice <voice> # Voice override
--model <model> # Deprecated; accepted but ignored
--instructions <text> # Per-identity steering prompt
inkbox phone hosted-agent authority-mode yolo -i <handle> # Saved inbound/outbound default; admin API keyVoice catalog entries include id, name, description, available, and
optional previewUrl. Unavailable entries remain visible; select an available
voice's ID with hosted-agent set --voice. The catalog's defaultVoice is
returned alongside the entries in JSON output. Config setters are a full
replacement: read the current config first and include its existing
--instructions when changing only the voice.
Shared origination uses the identity's active iMessage-line assignment and
does not require a dedicated phone number. The recipient must already have a
shared iMessage connection to the identity; otherwise the call fails with
409 no_shared_connection.
text
Text message (SMS/MMS) operations, scoped to an identity. Requires -i <handle>.
Outbound SMS rules:
- Allowed only from local numbers (not toll-free).
- 100 recipient sends per phone number per rolling 24h — a 3-recipient group message counts as 3 recipient sends. A single accepted send may push usage past the cap; the next capped send returns
429 sender_rate_limited. - A freshly provisioned local number needs ~10-15 minutes for 10DLC carrier propagation. Check
inkbox number get <id>: send is gated untilsmsStatusreachesready. - Recipients must opt in by texting
STARTto any number in your organization. Unknown recipients fail with403 recipient_not_opted_in; opt-outs (STOP) return403 recipient_opted_out. - Beta: Group MMS and conversation sends are beta. Some carriers may reject group chats or MMS from 10DLC numbers even when the sender is ready and recipients have opted in.
Customer-managed 10DLC brands/campaigns lift the default per-number cap to the carrier-assigned tier. Toll-free SMS sending is still coming soon.
inkbox text send -i <handle> # Send an outbound SMS/MMS
--to <e164[,e164...]> # One recipient or a comma-separated group
--conversation-id <uuid> # Reply into an existing conversation instead of --to
--text <body> # Message body
--media-url <url> # MMS media URL; repeat for multiple
inkbox text list -i <handle> # List text messages
--limit <n> # Max results (default: 50)
--offset <n> # Pagination offset (default: 0)
--unread-only # Show only unread messages
inkbox text get <text-id> -i <handle> # Get a single text message
inkbox text conversations -i <handle> # List conversation summaries
--limit <n> # Max results (default: 50)
--offset <n> # Pagination offset (default: 0)
--include-groups # Include group conversations
inkbox text conversation <conversation-key> -i <handle> # Remote number or conversation UUID
--limit <n> # Max results (default: 50)
--offset <n> # Pagination offset (default: 0)
inkbox text search -i <handle> # Search text messages
-q, --query <query> # Search query (required)
--limit <n> # Max results (default: 50)
inkbox text mark-read <text-id> -i <handle> # Mark a text as read
inkbox text mark-conversation-read <conversation-key> -i <handle> # Mark conversation as readimessage
iMessage over shared service or a dedicated line. Shared-service recipients connect first; dedicated identities may initiate one-to-one or group conversations.
inkbox imessage triage-number # Router number + the command humans text to connect
inkbox imessage send -i <handle> # Send or reply
--to <numbers> # One E.164 recipient or a comma-separated group
--conversation-id <id> # Existing conversation UUID to reply into
--text <text> # Message body
--media-url <url> # Media URL (at most one)
--send-style <style> # Expressive style for 1:1 or group sends
inkbox imessage list -i <handle> # List messages, newest first
--conversation-id <id> # Narrow to one conversation
--limit <n> # Max results (default: 50)
--offset <n> # Pagination offset (default: 0)
--unread-only # Show only unread messages
--include-groups # Include group messages
inkbox imessage assignments -i <handle> # List recipients currently connected to the identity
--limit <n> # Max results (default: 50)
--offset <n> # Pagination offset (default: 0)
inkbox imessage conversations -i <handle> # Conversation summaries with previews + unread counts
--include-groups # Include group conversations
inkbox imessage conversation <conversation-id> -i <handle> # Read one conversation's messages
inkbox imessage react <message-id> -i <handle> # React to an inbound 1:1 or group message
--reaction <kind> # love, like, dislike, laugh, emphasize, question, eyes
--part-index <n> # Part of a multi-part message (default: 0)
inkbox imessage unreact <reaction-id> -i <handle> # Take back a tapback this identity sent
inkbox imessage mark-conversation-read <conversation-id> -i <handle> # One-to-one only
inkbox imessage typing <conversation-id> -i <handle> # One-to-one only
inkbox imessage upload-media <file> -i <handle> # Upload a file, get a sendable media URL
--content-type <type> # MIME type of the file
inkbox imessage contact-rule list -i <handle> # Allow/block rules for the identity
inkbox imessage contact-rule create -i <handle> # Add a rule
--action <action> # 'allow' or 'block'
--match-target <number> # Phone number to match (E.164)
inkbox imessage contact-rule update <rule-id> -i <handle> --action allow|block
inkbox imessage contact-rule delete <rule-id> -i <handle> # Delete a rule (admin key)
inkbox imessage contact-rule list-all # Org-wide rule list (admin key)
--agent-identity-id <id> # Narrow to one identityThe same 13 expressive styles work on group creation and conversation-id
replies, including sends with --media-url:
inkbox imessage send -i <handle> --to +15551234567,+15557654321 --text "Hello group" --media-url https://example.com/group-photo.jpg --send-style confetti
inkbox imessage send -i <handle> --conversation-id <group-conversation-id> --text "Follow-up" --media-url https://example.com/follow-up.jpg --send-style lasersGroup conversation rows expose groupCreationStatus as creating,
not_created, or ready. A rejected initial creation stays on the same local
conversation; send again with its conversation id to retry. Successful retry
changes the status to ready.
a2a
# Admin-scoped API key: create, inspect, list, and revoke invitations.
inkbox a2a invites create --peer-agent-handle support billing \
--recipient-email [email protected]
inkbox a2a invites list --status pending
inkbox a2a invites show <invitation-id>
inkbox a2a invites revoke <invitation-id>
# No API key is required to preview an invitation.
inkbox a2a invites preview
# Claimed agent key only. The default prompt hides input; automation can set
# INKBOX_A2A_INVITATION or pipe the link/token with --invitation-stdin.
inkbox a2a invites accept
printf '%s' "$INKBOX_A2A_INVITATION" | inkbox a2a invites accept --invitation-stdin
# Receiver setup and advertised capabilities
inkbox a2a enable -i researcher
inkbox a2a settings -i researcher
inkbox a2a publicly-discoverable true -i researcher
inkbox a2a public-egress true -i researcher
inkbox a2a card -i researcher
inkbox a2a skills set -i researcher --file skills.json
# Search enabled agents. Organization scope is the default.
inkbox a2a directory --query support
inkbox a2a directory --public --query research --limit 25
# Bilateral admission for coordinator -> researcher calls
inkbox a2a rules add -i coordinator --handle researcher \
--action allow --direction outbound
inkbox a2a rules add -i researcher --handle coordinator \
--action allow --direction inbound
# Unified task history. Omit --direction for the receiver inbox.
inkbox a2a tasks -i coordinator --direction both \
--requester coordinator --worker researcher \
--state working --query "quarterly report" --limit 25
# Search individual messages with task and participant provenance.
inkbox a2a messages -i coordinator --direction outbound \
--worker researcher --role agent --query revenue --limit 25 --json
# Continue a cursor page with the same filters.
inkbox a2a messages -i coordinator --direction outbound \
--worker researcher --role agent --query revenue \
--cursor '<nextCursor>' --limit 25 --json
# The outbound alias lists only work requested by the identity.
inkbox a2a sent -i coordinator --worker researcher
inkbox a2a sent-task <task-id> -i coordinator
# List, inspect, and rename shared contexts. New contexts start as
# "New A2A Session"; that exact default may be named from the first message.
inkbox a2a contexts -i coordinator --direction both
inkbox a2a context <context-id> -i researcher
inkbox a2a sent-contexts -i coordinator
inkbox a2a sent-context <context-id> -i coordinator
inkbox a2a rename-context <context-id> -i coordinator \
--name "Quarterly Research Review"
# A context without a task starts a sibling task. Existing tasks continue
# independently when --task is supplied.
inkbox a2a call https://example.test/a2a/researcher/card \
-i coordinator --context <context-id> --text "Review the findings"
# A worker can request more input or finish a task.
inkbox a2a reply <task-id> -i researcher --ask --text "Which quarter?"
inkbox a2a reply <task-id> -i researcher --complete --text "Done."JSON list output contains both items and nextCursor. Human-readable output
prints a next-cursor hint when another page exists. Keyword search covers
string and numeric content values from text and data parts, excludes
metadata, and returns newest-first results rather than relevance ranking.
--role selects the message author (caller or agent), independent of task
direction. Task detail exposes messages and current state. A protocol call must
pass both the requester identity's outbound policy and the worker identity's
inbound policy. Contact-rule directions are inbound, outbound, and both.
Context-level requester and worker identify the original opener and recipient;
each task identifies its own direction, and tasks in both directions can run
concurrently. Cross-endpoint context reuse is supported between Inkbox
identities; external A2A services may behave differently.
vault
Encrypted vault operations. get, create, and credential listing require a vault key.
inkbox vault init # Initialize vault (creates primary + recovery keys)
--vault-key <key> # Vault key (or set INKBOX_VAULT_KEY)
inkbox vault info # Show vault info
inkbox vault secrets # List secrets (metadata only)
--type <type> # Filter: login, api_key, ssh_key, key_pair, other
inkbox vault get <secret-id> # Decrypt a secret (requires vault key)
inkbox vault delete <secret-id> # Delete a secret
inkbox vault create # Create a secret (requires vault key)
--name <name> # Secret name (required)
--type <type> # Secret type (required)
--description <desc> # Optional description
inkbox vault keys # List vault keys
--type <type> # Filter: primary or recovery
inkbox vault grant-access <secret-id> # Grant identity access to a secret
-i, --identity <handle> # Agent identity handle (required)
inkbox vault revoke-access <secret-id> # Revoke identity access to a secret
-i, --identity <handle> # Agent identity handle (required)
inkbox vault access-list <secret-id> # List access rules for a secret
inkbox vault logins -i <handle> # List login credentials (vault key)
inkbox vault api-keys -i <handle> # List API key credentials (vault key)
inkbox vault ssh-keys -i <handle> # List SSH key credentials (vault key)
inkbox vault key-pairs -i <handle> # List key pair credentials (vault key)Secret type flags:
# login
--password <pass> [--username <user>] [--email <email>] [--url <url>] [--totp-uri <uri>] [--notes <text>]
# api_key
--key <key> [--endpoint <url>] [--notes <text>]
# key_pair
--access-key <key> --secret-key <key> [--endpoint <url>] [--notes <text>]
# ssh_key
--private-key <key> [--public-key <key>] [--fingerprint <fp>] [--passphrase <pass>] [--notes <text>]
# other
--data <json> [--notes <text>]mailbox
Import historical mail from an MBOX or EML file, or a ZIP holding either (a Gmail Takeout ZIP imports as-is; ZIP entries that are not mail, including nested archives, are ignored):
inkbox mailbox imports run <email> <file>
--source-format <auto|mbox|eml|zip> # Default: auto
--original-address <email> # Repeatable; identifies sent mail
--mark-unread # Default imports as read
--no-wait # Return after queueing
--timeout <seconds> # Local wait timeout; does not cancel
--poll-interval <seconds> # Default: 5
inkbox mailbox imports get <email> <job-id>
inkbox mailbox imports list <email> [--cursor <cursor>] [--limit <n>]
inkbox mailbox imports wait <email> <job-id> [--timeout <seconds>] [--poll-interval <seconds>]
inkbox mailbox imports cancel <email> <job-id>run uploads from disk without loading the full file into memory. Upload and
processing progress goes to stderr; --json keeps stdout to one job object.
run and wait exit nonzero when the terminal job is failed or cancelled.
Unsafe imported content may be rejected and counted separately. Processing
counters are cumulative and never go backwards, but they can sit unchanged while
a large message is processed and are not a percentage. Jobs run one at a time
per organization and share overall import capacity, so a long queued stretch
is normal rather than a stall.
Upload targets expire after 5 minutes, so run re-issues one and retries once
after a transport failure or rejected upload target, then cancels the job it
created rather than leaving the mailbox blocked. If a run is interrupted,
inkbox mailbox imports list <email>
and inkbox mailbox imports cancel <email> <job-id> release the mailbox; an
abandoned job otherwise holds it for 24 hours. Other limits: 1 GiB per upload,
50 MiB per message, 100,000 messages and 20 --original-address values per job,
65,000 entries per ZIP, and 20 import jobs per organization per 24 hours.
Org-level mailbox read + update. Mailboxes are provisioned atomically
by inkbox identity create and removed by inkbox identity delete
(cascade) — there is no standalone create / delete here. display_name
has moved to the identity; mailbox PATCH hard-rejects it with a 422.
inkbox mailbox list # List all mailboxes (incl. a 'storage' column)
inkbox mailbox get <email-address> # Get mailbox details
inkbox mailbox update <email-address> # Update a mailbox
--filter-mode <mode> # whitelist or blacklist (admin-only)
inkbox mailbox client-settings <email-address> # IMAP/SMTP settings for a mail client
# To attach a webhook receiver, use `inkbox webhook subscription create
# --mailbox-id <id> --url <url> --event-type message.received ...`.mailbox list shows a storage column (1.2 GiB / 2 GiB) and mailbox get
adds storageUsedBytes / storageLimitBytes — raw byte counts under --json,
humanized in the table. The caps are binary (2 GiB is 2 * 1024³ bytes),
so the readouts are labeled GiB/MiB. A - limit means the server didn't
resolve a cap.
Sending from a mailbox that is at its cap fails with HTTP 402 and a hint:
free space with inkbox email delete <message-id> -i <handle> / inkbox email
delete-thread <thread-id> -i <handle> (reclaim is immediate), or upgrade the
plan. All three send paths (email send, email reply-all, email forward)
are enforced.
contacts
Organization-wide contacts, correspondence, and memory facts.
inkbox contacts list [--review-status <status>] [--offset <n>] # Offset max: 10000
inkbox contacts get <contact-id>
inkbox contacts facts list <contact-id> [--include-expired]
inkbox contacts facts get <contact-id> <fact-id>
inkbox contacts facts citation <contact-id> <fact-id> <citation-id>
inkbox contacts facts citation-url <source-url>
inkbox contacts facts create <contact-id> --content <text> --kind <kind> # Admin-scoped API key required
inkbox contacts facts update <contact-id> <fact-id> [--content <text>] [--kind <kind>] # Admin-scoped API key required
inkbox contacts facts delete <contact-id> <fact-id> # Admin-scoped API key required
inkbox contacts correspondence <contact-id> [-i <identity-id>]
[--channels <channel>] [--after <datetime>] [--before <datetime>]
[--limit-per-channel <n>] [--content <mode>] [--transcripts <mode>]
inkbox contacts merge <survivor-id> --losing <contact-id...> # Admin-scoped API key required
[--field-sources '{"preferredName":"<contact-id>"}']
inkbox contacts create --json <payload>
inkbox contacts update <contact-id> --json <patch>
inkbox contacts delete <contact-id>
inkbox contacts bulk-delete <contact-id...>
inkbox contacts import <file.vcf>
inkbox contacts export-many <contact-id...> [--out <file>]
inkbox contacts access list <contact-id> # Compatibility read only
inkbox contacts access get <handle> <contact-id>
inkbox contacts access set <handle> <contact-id> --file <access.json>
inkbox contacts permissions get <handle> <contact-id>
inkbox contacts permissions set <handle> <contact-id> --file <permissions.json>
inkbox contacts communication-policy get <contact-id> [--identity-id <uuid>]
inkbox contacts communication-policy set <contact-id> --file <policy.json>
inkbox contacts communication-policy preview <contact-id> <identity-id>
inkbox contacts communication-policy list <handle>
inkbox contacts communication-policy list-management <handle>
inkbox identity contact-policies <handle>Active memories have per-kind and contact-wide limits. A merge is rejected
atomically when either would be exceeded. Delete a fact from each kind named by
the error, or any active fact when it names total, then retry. Untyped memories
recorded before kinds existed count toward the total.
A fact's kind is profile (who the contact is), preference (a standing
instruction), or context (a live situation). Unlocked context facts recorded
by extraction carry an expiresAt and drop out of facts list once it passes;
locked facts remain active. Pass --include-expired to see expired facts.
Hand-written facts never expire. Any update makes a fact manually maintained,
clears its expiry, and revives it if needed. Changing content also removes its
confidence and source links; changing only the kind preserves them.
tunnel
Tunnel read + update + sign-csr. Tunnels are provisioned atomically by
inkbox identity create and removed by inkbox identity delete
(cascade) — there is no standalone create / delete / restore /
rotate-secret surface.
inkbox tunnel list # List org tunnels
inkbox tunnel get <id-or-handle> # By UUID or agent handle
inkbox tunnel update <id> # Edit metadata
--metadata <json> # JSON object; "{}" to clear
inkbox tunnel sign-csr <id> # Passthrough cert signing
--csr <path-or-pem> # CSR file path OR inline PEM
--out <path> # Write cert+chain (default: stdout)domain
Custom sending-domain management. Registration, DNS, verification, DKIM rotation, and deletion stay in the console; the CLI exposes only the read-and-default surface.
inkbox domain list # List custom sending domains
--status <status> # Filter by status (e.g. 'verified')
inkbox domain set-default <domain-name> # Set the org default (admin-scoped API key)
# Pass the platform domain (e.g. 'inkboxmail.com') to revertnumber
Org-level phone number management.
inkbox number list # List all phone numbers
inkbox number get <id> # Get phone number details
inkbox number provision # Provision a new number
--handle <handle> # Agent handle (required)
--type <type> # local (default); toll_free is no longer offered (422)
--state <state> # US state abbreviation (for local)
inkbox number update <id> # Update phone number config
--incoming-call-action <action> # auto_accept, auto_reject, webhook,
# or hosted_agent (needs no URL)
--client-websocket-url <url> # WebSocket URL for audio bridging
--incoming-call-webhook-url <url> # Webhook URL for incoming calls
inkbox number release <number-id> # Release a phone number
# To attach a text-webhook receiver, use `inkbox webhook subscription
# create --phone-number-id <id> --url <url> --event-type text.received ...`.whoami
Show the authenticated caller's identity.
inkbox whoami # Display caller identity (API key or JWT)
inkbox whoami --json # Output as JSONsigning-key
Webhook signing key management.
inkbox signing-key create # Create or rotate signing keywebhook
Webhook utilities.
inkbox webhook verify # Verify a webhook signature (local)
--payload <payload> # Raw request body (required)
--secret <secret> # Signing key (required)
-H, --header <header> # Header in Key: Value format (repeatable)
inkbox webhook subscription list # List webhook subscriptions
--mailbox-id <id> # Filter by owning mailbox id
--phone-number-id <id> # Filter by owning phone number id
--agent-identity-id <id> # Filter by owning agent identity id (iMessage / call.ended)
--url <url> # Filter by destination URL (exact)
--event-type <type> # Filter by event_type wire value
inkbox webhook subscription get <sub-id> # Get one subscription
inkbox webhook subscription create # Create a subscription
--mailbox-id <id> # Owning mailbox id (exactly one of the
--phone-number-id <id> # three owner FKs is required)
--agent-identity-id <id> # Owning agent identity id (iMessage / call.ended events)
--url <url> # HTTPS destination (required)
--event-type <type> # Event type (repeatable; ≥1 required)
--context-email <spec> # Conversation context for the email
# class: count:N or window:H
--context-texts <spec> # Same for texts (count:N | window:H)
--context-calls <spec> # Same for calls (count:N | window:H)
--auth-token-stdin # Read the delivery bearer token from
# stdin (never passed as an argument).
# Reads return the token; list tables
# show only hasAuthToken
inkbox webhook subscription update <sub-id> # Update url, event_types, context, and/or auth token
--url <url> # New HTTPS destination
--event-type <type> # Replacement event-type list (repeatable)
--context-email <spec> # Replace email context (count:N | window:H)
--context-texts <spec> # Replace texts context (count:N | window:H)
--context-calls <spec> # Replace calls context (count:N | window:H)
--clear-context # Clear all conversation context
# (mutually exclusive with --context-*)
--auth-token-stdin # Replace the bearer token, read from stdin
--clear-auth-token # Clear the delivery bearer token
# (mutually exclusive with
# --auth-token-stdin)
inkbox webhook subscription delete <sub-id> # Remove a subscriptionMail clients (IMAP/SMTP)
An Inkbox inbox can also be attached to a regular mail client (Thunderbird,
Apple Mail, mutt, …) with the API key you already have. There is no separate
credential to create. inkbox mailbox client-settings <email-address> prints
these:
| Setting | Value |
|---|---|
| IMAP host | imap.inkboxmail.com |
| IMAP port | 993 (IMAPS / implicit TLS) |
| SMTP host | smtp.inkboxmail.com |
| SMTP port | 465 (SMTPS / implicit TLS) or 587 (STARTTLS) |
| Username | the inbox address (e.g. [email protected]) |
| Password | an identity-scoped API key (ApiKey_...) |
Mint the password with inkbox api-keys create --label <name> --identity-id
<uuid>. Admin-scoped keys are rejected: one key maps to exactly one mailbox.
Revoking the key revokes mail-client access.
Two constraints that bite in practice:
Frommust be the authenticated inbox address, and exactly one address. Aliases and "send as" identities are rejected.- On the Free plan, signed/encrypted mail (S/MIME, PGP) cannot be sent over SMTP. The required footer can't be injected without breaking the signature, so the send is refused. Send unsigned, or upgrade the plan.
If your client saves its own copy of sent messages, leave that setting on: Inkbox recognizes the copy as the message it already stored, so you get one Sent entry, charged against your storage cap once.
mailbox client-settings derives the hosts from the configured API base URL.
When that URL isn't a recognized Inkbox API host, it errors instead of printing
hosts it would have to guess — a mail client pointed at guessed hosts would talk
to the wrong server.
Full setup walkthrough: https://inkbox.ai/docs/capabilities/email/mail-clients
Global options
--api-key <key> Inkbox API key (or set INKBOX_API_KEY)
--vault-key <key> Vault key for decrypt operations (or set INKBOX_VAULT_KEY)
--base-url <url> Override API base URL
--json Output as JSON (default: formatted tables)Proxies
The CLI honors HTTP_PROXY / HTTPS_PROXY / NO_PROXY automatically on every supported Node version — no NODE_USE_ENV_PROXY needed. Set NODE_USE_ENV_PROXY=0 to opt out.
Custom email signatures
Custom signatures are saved per mailbox and require an eligible paid plan to set or enable.
Each HTML/text field supports up to 16,384 characters. HTML is sanitized; logos
must use absolute HTTPS URLs. Updating HTML without text generates a plain-text
fallback. Omitted fields stay unchanged; null clears saved content. If saved text
is null, sending derives it from HTML when possible. Disable without deleting to
pause automatic insertion. Disabling and clearing remain available on every plan.
Signatures are inserted when mail is sent, including replies, forwards, and sent
drafts; do not append them manually. The Inkbox watermark is controlled separately.
Signed/encrypted SMTP mail cannot have a custom signature inserted; disable
automatic insertion before sending those messages.
A .sig file is not a standardized attachment format: read its UTF-8 text or HTML
content into the corresponding field; images and proprietary formats are not imported.
inkbox mailbox update [email protected] --signature-html-file signature.html --signature-enabled
inkbox mailbox update [email protected] --signature-text-file signature.sig
inkbox mailbox update [email protected] --no-signature-enabled
inkbox mailbox update [email protected] --clear-signature-html --clear-signature-text
inkbox mailbox get [email protected] --jsonInline content uses --signature-html <html> or --signature-text <text>.
For each format, choose inline content, a file, or its clear flag, not more than one.
License
MIT
