Inkbox Onboarding
Use this skill after an API key exists. If the agent still needs an account or
API key, use inkbox-agent-self-signup first.
Onboarding Process
- Confirm which Inkbox API key and identity should be used. Never print, log, or commit the key.
- Inspect the authenticated principal and current identities before creating or changing anything.
- Check each requested channel independently. A working mailbox does not imply that SMS, calls, or iMessage are ready.
- Ask before provisioning a number, enabling a channel, changing inbound routing, creating a webhook, or sending test traffic.
- Complete any recipient-side connection or consent step.
- Run one bounded test per requested channel and verify the resulting record or reply instead of assuming an accepted request was delivered.
- Choose an inbound strategy: polling for simple agents, signed webhooks for event-driven agents, or both.
- Offer recurring inbox and conversation triage only after the channels are ready. Confirm cadence, channels, identities, and whether replies are allowed.
Readiness Checklist
| Channel | Ready when | Recipient-side step |
|---|---|---|
| The identity has a mailbox | None | |
| SMS/MMS | The identity has a local phone number and its SMS status is ready |
The recipient must text START before the first outbound message |
| Calls | The identity has a phone number, or a supported connected shared iMessage line is selected for the call | Shared-line calls require an existing iMessage connection |
| iMessage, shared service | iMessage is enabled for the identity | The person texts the runtime-provided connect @handle command to the current router number |
| iMessage, dedicated line | iMessage is enabled and a dedicated line is attached | Server-side contact policy must allow the send |
Identity creation provisions a mailbox and tunnel together. A phone number is
optional and must be local; do not request a toll-free number. New local numbers
can remain pending while messaging registration completes, so inspect
sms_status and wait for ready rather than retrying sends.
Router numbers and connection commands can change. Always retrieve the current iMessage triage details at runtime and present them exactly as returned.
CLI
Install the CLI and keep the key in the environment:
npm install -g @inkbox/cli
export INKBOX_API_KEY="ApiKey_..."
Inspect before mutating:
inkbox whoami --json
inkbox identity list
inkbox identity get support-agent --json
With the user's approval, enable or provision only the requested channels:
inkbox identity update support-agent --imessage-enabled true
inkbox number provision --handle support-agent --type local --state NY
inkbox imessage triage-number
After number provisioning, run inkbox identity get support-agent --json again and
wait for smsStatus to become ready. Before texting a recipient, verify that
the recipient has opted in:
inkbox sms-opt-in get +15551234567
Use --json when another program will consume the output. Sending email, text,
iMessage, or a call creates real external traffic and requires confirmation.
Python SDK
import os
from inkbox import Inkbox
with Inkbox(api_key=os.environ["INKBOX_API_KEY"]) as inkbox:
principal = inkbox.whoami()
identities = inkbox.list_identities()
identity = inkbox.get_identity("support-agent")
print(principal.auth_type)
print(identity.mailbox)
print(identity.phone_number)
print(identity.imessage_enabled)
# Mutations require the user's approval.
# identity.update(imessage_enabled=True)
# identity.provision_phone_number(type="local", state="NY")
triage = inkbox.imessages.get_triage_number()
print(triage.number, triage.connect_command)
After provisioning a number, refresh the identity before checking readiness:
identity.refresh()
if identity.phone_number is not None:
print(identity.phone_number.sms_status)
For channel-specific operations, continue with inkbox-python rather than
guessing method names or response fields.
TypeScript SDK
import { Inkbox } from "@inkbox/sdk";
const inkbox = new Inkbox({ apiKey: process.env.INKBOX_API_KEY! });
const principal = await inkbox.whoami();
const identities = await inkbox.listIdentities();
const identity = await inkbox.getIdentity("support-agent");
console.log(principal.authType);
console.log(identity.mailbox);
console.log(identity.phoneNumber);
console.log(identity.imessageEnabled);
// Mutations require the user's approval.
// await identity.update({ imessageEnabled: true });
// await identity.provisionPhoneNumber({ type: "local", state: "NY" });
const triage = await inkbox.imessages.getTriageNumber();
console.log(triage.number, triage.connectCommand);
Refresh after provisioning before checking identity.phoneNumber?.smsStatus:
await identity.refresh();
console.log(identity.phoneNumber?.smsStatus);
For channel-specific operations, continue with inkbox-ts.
Direct API
The API uses the same key and returns snake_case JSON:
export INKBOX_API_KEY="ApiKey_..."
curl -sS https://inkbox.ai/api/v1/whoami \
-H "X-API-Key: ${INKBOX_API_KEY}"
curl -sS https://inkbox.ai/api/v1/identities \
-H "X-API-Key: ${INKBOX_API_KEY}"
curl -sS https://inkbox.ai/api/v1/identities/support-agent \
-H "X-API-Key: ${INKBOX_API_KEY}"
These mutations require confirmation:
curl -sS -X PATCH https://inkbox.ai/api/v1/identities/support-agent \
-H "X-API-Key: ${INKBOX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"imessage_enabled":true}'
curl -sS -X POST https://inkbox.ai/api/v1/phone/numbers \
-H "X-API-Key: ${INKBOX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"agent_handle":"support-agent","type":"local","state":"NY"}'
Use the published OpenAPI document at
https://inkbox.ai/api/openapi.json for complete request and response schemas.
Inbound Communications
Polling is the smallest setup for an agent that already runs on a schedule. List unread email and recent SMS, iMessage, calls, and A2A tasks; fetch only the bounded conversation context needed; then persist a cursor or last-success time so the next run does not reply twice.
Use webhooks when the agent needs prompt delivery. Subscribe to only the event
types and identity resources the agent needs, verify every signature against the
raw request body, return quickly, and process idempotently. Use an Inkbox tunnel
when the receiver runs locally; see inkbox-tunnels for setup and recovery.
Recurring Triage
When the client supports scheduling, offer a task with an explicit cadence and scope. A safe default instruction is:
Check unread email, new SMS and iMessage conversations, recent or missed calls, and new or input-required A2A tasks since the last successful run. Read only the context needed to understand each item. Reply only where the schedule explicitly allows it, use the same channel, never respond twice, and report sends that fail. Finish with actions taken, items needing a decision, and any channel setup problems.
Do not create a schedule or authorize automatic replies without the user's approval.