Python SDK for the Inkbox API — API-first communication infrastructure for AI agents (email, phone, identities).
pip install inkboxRequires Python ≥ 3.11.
You'll need an API key to use this SDK. Get one at console.inkbox.ai.
importosfrominkboximportInkboxwithInkbox(api_key=os.environ["INKBOX_API_KEY"]) asinkbox:
# Create an agent identityidentity=inkbox.create_identity("support-bot")
# Create and link new channelsidentity.create_mailbox(display_name="Support Bot")
identity.provision_phone_number(type="toll_free")
# Send email directly from the identityidentity.send_email(
to=["customer@example.com"],
subject="Your order has shipped",
body_text="Tracking number: 1Z999AA10123456784",
)
# Place an outbound callidentity.place_call(
to_number="+18005559999",
client_websocket_url="wss://my-app.com/voice",
)
# Read inboxformessageinidentity.iter_emails():
print(message.subject)
# List callscalls=identity.list_calls()| Argument | Type | Default | Description |
|---|---|---|---|
api_key | str | required | Your ApiKey_... token |
base_url | str | API default | Override for self-hosting or testing |
timeout | float | 30.0 | Request timeout in seconds |
Use with Inkbox(...) as inkbox: (recommended) or call inkbox.close() manually to clean up HTTP connections.
inkbox.create_identity() and inkbox.get_identity() return an AgentIdentity object that holds the identity's channels and exposes convenience methods scoped to those channels.
# Create and fully provision an identityidentity=inkbox.create_identity("sales-bot")
mailbox=identity.create_mailbox(display_name="Sales Bot") # creates + linksphone=identity.provision_phone_number(type="toll_free") # provisions + linksprint(mailbox.email_address)
print(phone.number)
# Link an existing mailbox or phone number instead of creating new onesidentity.assign_mailbox("mailbox-uuid-here")
identity.assign_phone_number("phone-number-uuid-here")
# Get an existing identityidentity=inkbox.get_identity("sales-bot")
identity.refresh() # re-fetch channels from API# List all identities for your orgall_identities=inkbox.list_identities()
# Update status or handleidentity.update(status="paused")
identity.update(new_handle="sales-bot-v2")
# Unlink channels (without deleting them)identity.unlink_mailbox()
identity.unlink_phone_number()
# Deleteidentity.delete()# Send an email (plain text and/or HTML)sent=identity.send_email(
to=["user@example.com"],
subject="Hello from Inkbox",
body_text="Hi there!",
body_html="<p>Hi there!</p>",
cc=["manager@example.com"],
bcc=["archive@example.com"],
)
# Send a threaded replyidentity.send_email(
to=["user@example.com"],
subject=f"Re: {sent.subject}",
body_text="Following up!",
in_reply_to_message_id=sent.id,
)
# Send with attachmentsidentity.send_email(
to=["user@example.com"],
subject="See attached",
body_text="Please find the file attached.",
attachments=[{
"filename": "report.pdf",
"content_type": "application/pdf",
"content_base64": "<base64-encoded-content>",
}],
)
# Iterate inbox (paginated automatically)formsginidentity.iter_emails():
print(msg.subject, msg.from_address, msg.is_read)
# Filter by direction: "inbound" or "outbound"formsginidentity.iter_emails(direction="inbound"):
print(msg.subject)
# Iterate only unread emailsformsginidentity.iter_unread_emails():
print(msg.subject)
# Mark messages as readidentity.mark_emails_read([msg.idformsginidentity.iter_unread_emails()])
# Get all emails in a thread (thread_id comes from msg.thread_id)thread=identity.get_thread(msg.thread_id)
forminthread.messages:
print(m.subject, m.from_address)# Place an outbound call — stream audio over WebSocketcall=identity.place_call(
to_number="+15167251294",
client_websocket_url="wss://your-agent.example.com/ws",
)
print(call.status, call.rate_limit.calls_remaining)
# Or receive call events via webhook insteadcall=identity.place_call(
to_number="+15167251294",
webhook_url="https://your-agent.example.com/call-events",
)
# List calls (paginated)calls=identity.list_calls(limit=10, offset=0)
forcallincalls:
print(call.id, call.direction, call.remote_phone_number, call.status)
# Fetch transcript segments for a callsegments=identity.list_transcripts(calls[0].id)
fortinsegments:
print(f"[{t.party}] {t.text}") # party: "local" or "remote"# Read transcripts across all recent callsforcallinidentity.list_calls(limit=10):
segments=identity.list_transcripts(call.id)
ifnotsegments:
continueprint(f"\n--- Call {call.id} ({call.direction}) ---")
fortinsegments:
print(f" [{t.party:6}] {t.text}")
# Filter to only the remote party's speechfortinidentity.list_transcripts(calls[0].id):
ift.party=="remote":
print(t.text)
# Search transcripts across a phone number (org-level)hits=inkbox.phone_numbers.search_transcripts(phone.id, q="refund", party="remote")
fortinhits:
print(f"[{t.party}] {t.text}")Manage mailboxes directly without going through an identity. Access via inkbox.mailboxes.
# List all mailboxes in the organisationmailboxes=inkbox.mailboxes.list()
# Get a specific mailboxmailbox=inkbox.mailboxes.get("abc-xyz@inkboxmail.com")
# Create a mailbox linked to an agent identitymailbox=inkbox.mailboxes.create(agent_handle="support-agent", display_name="Support Inbox")
print(mailbox.email_address)
# Update display name or webhook URLinkbox.mailboxes.update(mailbox.email_address, display_name="New Name")
inkbox.mailboxes.update(mailbox.email_address, webhook_url="https://example.com/hook")
inkbox.mailboxes.update(mailbox.email_address, webhook_url=None) # remove webhook# Full-text search across messages in a mailboxresults=inkbox.mailboxes.search(mailbox.email_address, q="invoice", limit=20)
formsginresults:
print(msg.subject, msg.from_address)
# Delete a mailboxinkbox.mailboxes.delete(mailbox.email_address)Manage phone numbers directly without going through an identity. Access via inkbox.phone_numbers.
# List all phone numbers in the organisationnumbers=inkbox.phone_numbers.list()
# Get a specific phone number by IDnumber=inkbox.phone_numbers.get("phone-number-uuid")
# Provision a new numbernumber=inkbox.phone_numbers.provision(type="toll_free")
local=inkbox.phone_numbers.provision(type="local", state="NY")
# Update incoming call behaviourinkbox.phone_numbers.update(
number.id,
incoming_call_action="webhook",
incoming_call_webhook_url="https://example.com/calls",
)
inkbox.phone_numbers.update(
number.id,
incoming_call_action="auto_accept",
client_websocket_url="wss://example.com/ws",
)
# Full-text search across transcriptshits=inkbox.phone_numbers.search_transcripts(number.id, q="refund", party="remote")
fortinhits:
print(f"[{t.party}] {t.text}")
# Release a numberinkbox.phone_numbers.release(number=number.number)Webhooks are configured on the mailbox or phone number resource — no separate registration step.
Set a URL on a mailbox to receive message.received and message.sent events.
# Set webhookinkbox.mailboxes.update("abc@inkboxmail.com", webhook_url="https://example.com/hook")
# Remove webhookinkbox.mailboxes.update("abc@inkboxmail.com", webhook_url=None)Set an incoming call webhook URL and action on a phone number.
# Route incoming calls to a webhookinkbox.phone_numbers.update(
number.id,
incoming_call_action="webhook",
incoming_call_webhook_url="https://example.com/calls",
)You can also supply a per-call webhook URL when placing a call:
identity.place_call(to_number="+15005550006", webhook_url="https://example.com/call-events")# Create or rotate the org-level webhook signing key (plaintext returned once)key=inkbox.create_signing_key()
print(key.signing_key) # save this immediatelyUse verify_webhook to confirm that an incoming request was sent by Inkbox.
frominkboximportverify_webhook# FastAPI@app.post("/hooks/mail")asyncdefmail_hook(request: Request):
raw_body=awaitrequest.body()
ifnotverify_webhook(
payload=raw_body,
headers=request.headers,
secret="whsec_...",
):
raiseHTTPException(status_code=403)
...
# Flask@app.post("/hooks/mail")defmail_hook():
raw_body=request.get_data()
ifnotverify_webhook(
payload=raw_body,
headers=request.headers,
secret="whsec_...",
):
abort(403)
...Runnable example scripts are available in the examples/python directory:
| Script | What it demonstrates |
|---|---|
register_agent_identity.py | Create an identity, assign mailbox + phone number |
agent_send_email.py | Send an email and a threaded reply |
read_agent_messages.py | List messages and threads |
create_agent_mailbox.py | Create, update, search, and delete a mailbox |
create_agent_phone_number.py | Provision, update, and release a number |
list_agent_phone_numbers.py | List all phone numbers in the org |
read_agent_calls.py | List calls and print transcripts |
receive_agent_email_webhook.py | Register and delete a mailbox webhook |
receive_agent_call_webhook.py | Register, update, and delete a phone webhook |
MIT