# AI Inbx > Email infrastructure for software that holds conversations. Send, receive, thread, and reply over one API. # AI Inbx documentation Source: https://docs.aiinbx.com/ AI Inbx provides APIs for sending email, receiving messages, and managing conversations. Use it to build transactional email, customer communication, or email agents with verified domains and connected Gmail or Outlook accounts. Each email belongs to a [thread](/guides/threads). Reply with a thread ID and message content; the API derives the sender, recipients, subject, and reply headers. [Signed webhooks](/webhooks) notify your application about incoming messages and delivery outcomes. **[Quickstart](/quickstart)** Create a key, configure a sender, and send your first email. **[API reference](/api)** Every endpoint, generated from the schemas the API validates against. **[TypeScript SDK](/sdks/typescript)** Dependency-free, typed, works on Node, Bun, Deno, and edge runtimes. **[Python SDK](/sdks/python)** Sync and async clients with the same resource surface. Read [Core concepts](/concepts) for the resource model, or choose a framework from [Integrations](/integrations). ## What it does **Send** HTML or text, attachments, custom headers, idempotent retries, and sends scheduled up to 30 days out. **Receive** Inbound mail on any domain you can publish DNS for, or through a connected Gmail or Outlook mailbox, delivered as webhooks. **Thread** Replies land on the conversation they belong to, matched on headers and quoted content rather than subject alone. **Find conversations** List threads by subject or participant, filter by mailbox or space, and paginate through their messages. **Suppress** Bounces, complaints, and unsubscribes stop the next send automatically, per list or across the org. **Pace** Sending windows, rate ceilings, and a queue you can inspect and release by hand. ## Choose your starting point | You want to | Start here | | --- | --- | | Send from a domain you control | [Quickstart](/quickstart) | | Connect an existing Gmail or Outlook account | [Mailboxes](/guides/mailboxes) | | Provide email for multiple customers | [Spaces](/guides/spaces) | | Build an automated email workflow | [Email agents](/integrations/agents) | | Prepare an integration for production | [Production guide](/guides/production) | | Give a coding agent the API contract | [Documentation for agents](/reference/agents) | | Work in AI Inbx from Claude, ChatGPT or Cursor | [MCP server](/mcp) | | Give an agent an email address of its own | [Agent inbox](/guides/agent-inbox) | | Run AI Inbx from a terminal or script | [CLI](/cli) | ## Send an email Install an [SDK](/sdks), set `AI_INBX_API_KEY`, and configure a [verified sending domain](/guides/domains) or [connected mailbox](/guides/mailboxes). Replace the example addresses with your sender and a recipient you control. ```ts TypeScript import AIInbx from "aiinbx" const aiinbx = new AIInbx() // reads AI_INBX_API_KEY const email = await aiinbx.emails.send({ from: { name: "Ada", address: "ada@example.com" }, to: "grace@example.com", subject: "Quick question", text: "Does Thursday still work for the review?", }) console.log(email.id, email.thread_id) ``` ```python Python from aiinbx import AIInbx with AIInbx() as client: # reads AI_INBX_API_KEY email = client.emails.send( { "from_": {"name": "Ada", "address": "ada@example.com"}, "to": ["grace@example.com"], "subject": "Quick question", "text": "Does Thursday still work for the review?", } ) print(email["id"], email["thread_id"]) ``` ```bash curl curl https://api.aiinbx.com/api/v2/emails \ -H "Authorization: Bearer $AI_INBX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "Ada ", "to": "grace@example.com", "subject": "Quick question", "text": "Does Thursday still work for the review?" }' ``` When Grace replies, an [`email.received`](/webhooks/events/email-received) webhook arrives carrying the same `thread_id`, and [`threads.reply`](/guides/threads#replying) continues the conversation without you rebuilding a single header. ## Where to go next **[Sending](/guides/sending)** Addresses, content, attachments, and idempotency. **[Receiving](/guides/receiving)** Domains and mailboxes as two ways in. **[Webhooks](/webhooks)** Endpoints, routing, retries, and signature verification. **[Conventions](/reference/conventions)** IDs, pagination, request IDs, and idempotency in one place. --- # API reference Source: https://docs.aiinbx.com/api **Base URL** · `https://api.aiinbx.com/api/v2` New to AI Inbx? Follow the [quickstart](/quickstart) for a complete send-and-reply flow. For an existing integration, start with [authentication](/authentication), [request conventions](/reference/conventions), or [errors](/reference/errors). ## Email and conversations [#email] **[Emails](/api/emails)** Send, retrieve, schedule, and cancel messages. **[Threads](/api/threads)** Read conversations, reply, and forward a transcript. **[Attachments](/api/attachments)** Download original files and prepared text. ## Sending identities [#identities] **[Domains](/api/domains)** Configure domains, verify DNS, and diagnose setup. **[Mailboxes](/api/mailboxes)** Connect and manage Gmail or Outlook accounts. **[OAuth apps](/api/oauth-apps)** Manage the apps used for mailbox authorization. ## Platform and delivery [#platform] **[Spaces](/api/spaces)** Group customer identities, messages, and controls. **[Webhooks](/api/webhooks)** Register endpoints, inspect deliveries, and replay failures. **[Events](/api/events)** Read back what happened, and catch up after missed webhooks. **[Suppressions](/api/suppressions)** Manage recipient exclusions and subscription preferences. **[Pacing](/api/pacing)** Set sending rules and inspect or release held mail. **[Workspace](/api/workspace)** Rename the workspace and set tracking defaults for new domains. **[Members](/api/members)** Invite people, change their roles, and remove them. **[API keys](/api/api-keys)** Create scoped credentials and manage their lifecycle. **[Webhook events](/webhooks/events)** Understand event payloads and delivery outcomes. ## SDKs and tools [#tools] Use the official [TypeScript](/sdks/typescript) or [Python](/sdks/python) SDK, or call the API over HTTP. The [OpenAPI document](https://api.aiinbx.com/api/v2/openapi.json) defines the wire contract. [Documentation for agents](/reference/agents) explains Markdown access and implementation conventions. For a complete list across resources, see [All endpoints](/api/endpoints). --- # API Keys API Source: https://docs.aiinbx.com/api/api-keys {/* Generated by scripts/openapi.ts from the shared API contract. */} Create and delete credentials for API access. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List API keys](/api/endpoints/api-keys/list-api-keys) | `/api-keys` | | `POST` | [Create an API key](/api/endpoints/api-keys/create-api-key) | `/api-keys` | | `DELETE` | [Delete an API key](/api/endpoints/api-keys/delete-api-key) | `/api-keys/{key_id}` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Attachments API Source: https://docs.aiinbx.com/api/attachments {/* Generated by scripts/openapi.ts from the shared API contract. */} Download original and prepared attachment content. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [Download an attachment](/api/endpoints/attachments/download-attachment) | `/attachments/{attachment_id}` | | `HEAD` | [Inspect attachment metadata](/api/endpoints/attachments/inspect-attachment) | `/attachments/{attachment_id}` | | `GET` | [Download prepared attachment text](/api/endpoints/attachments/retrieve-attachment-content) | `/attachments/{attachment_id}/content` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Domains API Source: https://docs.aiinbx.com/api/domains {/* Generated by scripts/openapi.ts from the shared API contract. */} Manage sending domains and DNS checks. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List domains](/api/endpoints/domains/list-domains) | `/domains` | | `POST` | [Create a domain](/api/endpoints/domains/create-domain) | `/domains` | | `GET` | [Retrieve a domain](/api/endpoints/domains/retrieve-domain) | `/domains/{domain_id}` | | `DELETE` | [Delete a domain](/api/endpoints/domains/delete-domain) | `/domains/{domain_id}` | | `PATCH` | [Update domain tracking settings](/api/endpoints/domains/update-domain) | `/domains/{domain_id}` | | `POST` | [Verify domain DNS records now](/api/endpoints/domains/verify-domain) | `/domains/{domain_id}/verify` | | `GET` | [Diagnose domain DNS configuration](/api/endpoints/domains/retrieve-domain-diagnostics) | `/domains/{domain_id}/diagnostics` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Emails API Source: https://docs.aiinbx.com/api/emails {/* Generated by scripts/openapi.ts from the shared API contract. */} Send, inspect, and schedule email. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List emails](/api/endpoints/emails/list-emails) | `/emails` | | `POST` | [Send an email](/api/endpoints/emails/send-email) | `/emails` | | `GET` | [Retrieve an email](/api/endpoints/emails/retrieve-email) | `/emails/{email_id}` | | `PATCH` | [Update an email](/api/endpoints/emails/update-email) | `/emails/{email_id}` | | `POST` | [Send a draft](/api/endpoints/emails/send-draft) | `/emails/{email_id}/send` | | `POST` | [Cancel an email](/api/endpoints/emails/cancel-email) | `/emails/{email_id}/cancel` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # AI Inbx API Source: https://docs.aiinbx.com/api/endpoints Email infrastructure for software that holds conversations: send, receive, thread and reply over one REST API, with a webhook for every event. Version 2.0.0 Base URL: `https://api.aiinbx.com/api/v2` ## Spaces Group a workspace's domains, mailboxes and mail by customer. Optional: a workspace that is not a platform never needs one. - [`GET /spaces`](/api/endpoints/spaces/list-spaces) — List spaces. - [`POST /spaces`](/api/endpoints/spaces/create-space) — Create a space. - [`GET /spaces/{space_id}`](/api/endpoints/spaces/retrieve-space) — Retrieve a space. - [`DELETE /spaces/{space_id}`](/api/endpoints/spaces/delete-space) — Delete a space. - [`PATCH /spaces/{space_id}`](/api/endpoints/spaces/update-space) — Update a space. ## API Keys Create and delete credentials for API access. - [`GET /api-keys`](/api/endpoints/api-keys/list-api-keys) — List API keys. - [`POST /api-keys`](/api/endpoints/api-keys/create-api-key) — Create an API key. - [`DELETE /api-keys/{key_id}`](/api/endpoints/api-keys/delete-api-key) — Delete an API key. ## Emails Send, inspect, and schedule email. - [`GET /emails`](/api/endpoints/emails/list-emails) — List emails. - [`POST /emails`](/api/endpoints/emails/send-email) — Send an email. - [`GET /emails/{email_id}`](/api/endpoints/emails/retrieve-email) — Retrieve an email. - [`PATCH /emails/{email_id}`](/api/endpoints/emails/update-email) — Update an email. - [`POST /emails/{email_id}/send`](/api/endpoints/emails/send-draft) — Send a draft. - [`POST /emails/{email_id}/cancel`](/api/endpoints/emails/cancel-email) — Cancel an email. ## Threads Read email conversations. - [`GET /threads`](/api/endpoints/threads/list-threads) — List threads. - [`GET /threads/{thread_id}`](/api/endpoints/threads/retrieve-thread) — Retrieve a thread. - [`POST /threads/{thread_id}/reply`](/api/endpoints/threads/reply-to-thread) — Reply in a thread. - [`POST /threads/{thread_id}/forward`](/api/endpoints/threads/forward-thread) — Forward a thread. ## Attachments Download original and prepared attachment content. - [`GET /attachments/{attachment_id}`](/api/endpoints/attachments/download-attachment) — Download an attachment. - [`HEAD /attachments/{attachment_id}`](/api/endpoints/attachments/inspect-attachment) — Inspect attachment metadata. - [`GET /attachments/{attachment_id}/content`](/api/endpoints/attachments/retrieve-attachment-content) — Download prepared attachment text. ## Domains Manage sending domains and DNS checks. - [`GET /domains`](/api/endpoints/domains/list-domains) — List domains. - [`POST /domains`](/api/endpoints/domains/create-domain) — Create a domain. - [`GET /domains/{domain_id}`](/api/endpoints/domains/retrieve-domain) — Retrieve a domain. - [`DELETE /domains/{domain_id}`](/api/endpoints/domains/delete-domain) — Delete a domain. - [`PATCH /domains/{domain_id}`](/api/endpoints/domains/update-domain) — Update domain tracking settings. - [`POST /domains/{domain_id}/verify`](/api/endpoints/domains/verify-domain) — Verify domain DNS records now. - [`GET /domains/{domain_id}/diagnostics`](/api/endpoints/domains/retrieve-domain-diagnostics) — Diagnose domain DNS configuration. ## Mailboxes Connect and manage provider mailboxes. - [`GET /mailboxes`](/api/endpoints/mailboxes/list-mailboxes) — List mailboxes. - [`POST /mailboxes/connect`](/api/endpoints/mailboxes/connect-mailbox) — Create a mailbox connection URL. - [`GET /mailboxes/{mailbox_id}`](/api/endpoints/mailboxes/retrieve-mailbox) — Retrieve a mailbox. - [`DELETE /mailboxes/{mailbox_id}`](/api/endpoints/mailboxes/disconnect-mailbox) — Disconnect a mailbox. - [`POST /mailboxes/{mailbox_id}/sync`](/api/endpoints/mailboxes/sync-mailbox) — Queue a mailbox sync. ## OAuth Apps Manage customer-owned Google and Microsoft OAuth apps. - [`GET /oauth-apps`](/api/endpoints/oauth-apps/list-o-auth-apps) — List OAuth apps. - [`POST /oauth-apps`](/api/endpoints/oauth-apps/create-o-auth-app) — Create an OAuth app. - [`GET /oauth-apps/{app_id}`](/api/endpoints/oauth-apps/retrieve-o-auth-app) — Retrieve an OAuth app. - [`DELETE /oauth-apps/{app_id}`](/api/endpoints/oauth-apps/delete-o-auth-app) — Delete an OAuth app. - [`PATCH /oauth-apps/{app_id}`](/api/endpoints/oauth-apps/update-o-auth-app) — Update an OAuth app. ## Webhooks Configure event delivery and inspect delivery attempts. - [`GET /webhook-endpoints`](/api/endpoints/webhooks/list-webhook-endpoints) — List webhook endpoints. - [`POST /webhook-endpoints`](/api/endpoints/webhooks/create-webhook-endpoint) — Create a webhook endpoint. - [`GET /webhook-endpoints/{endpoint_id}`](/api/endpoints/webhooks/retrieve-webhook-endpoint) — Retrieve a webhook endpoint. - [`DELETE /webhook-endpoints/{endpoint_id}`](/api/endpoints/webhooks/delete-webhook-endpoint) — Delete a webhook endpoint. - [`PATCH /webhook-endpoints/{endpoint_id}`](/api/endpoints/webhooks/update-webhook-endpoint) — Update a webhook endpoint. - [`POST /webhook-endpoints/{endpoint_id}/rotate-secret`](/api/endpoints/webhooks/rotate-webhook-secret) — Rotate a webhook signing secret. - [`POST /webhook-endpoints/{endpoint_id}/test`](/api/endpoints/webhooks/test-webhook-endpoint) — Send a test webhook. - [`GET /webhook-endpoints/{endpoint_id}/deliveries`](/api/endpoints/webhooks/list-webhook-deliveries) — List webhook deliveries. - [`POST /webhook-endpoints/{endpoint_id}/deliveries/retry`](/api/endpoints/webhooks/retry-webhook-deliveries) — Retry webhook deliveries. ## Events Read back what happened in the workspace — the events webhooks carry, whether or not an endpoint heard them. - [`GET /events`](/api/endpoints/events/list-events) — List events. - [`GET /events/{event_id}`](/api/endpoints/events/retrieve-event) — Retrieve an event. ## Webhook events What an endpoint receives: one request per event, each signed, in the envelope every event shares. - [`POST email.received`](/api/endpoints/webhook-events/email-received) — email.received. - [`POST email.sent`](/api/endpoints/webhook-events/email-sent) — email.sent. - [`POST email.delivered`](/api/endpoints/webhook-events/email-delivered) — email.delivered. - [`POST email.bounced`](/api/endpoints/webhook-events/email-bounced) — email.bounced. - [`POST email.complained`](/api/endpoints/webhook-events/email-complained) — email.complained. - [`POST email.failed`](/api/endpoints/webhook-events/email-failed) — email.failed. - [`POST email.unsubscribed`](/api/endpoints/webhook-events/email-unsubscribed) — email.unsubscribed. - [`POST email.opened`](/api/endpoints/webhook-events/email-opened) — email.opened. - [`POST email.clicked`](/api/endpoints/webhook-events/email-clicked) — email.clicked. - [`POST thread.created`](/api/endpoints/webhook-events/thread-created) — thread.created. - [`POST domain.verified`](/api/endpoints/webhook-events/domain-verified) — domain.verified. - [`POST domain.lost`](/api/endpoints/webhook-events/domain-lost) — domain.lost. - [`POST mailbox.connected`](/api/endpoints/webhook-events/mailbox-connected) — mailbox.connected. - [`POST mailbox.needs_reauth`](/api/endpoints/webhook-events/mailbox-needs-reauth) — mailbox.needs\_reauth. - [`POST mailbox.disconnected`](/api/endpoints/webhook-events/mailbox-disconnected) — mailbox.disconnected. ## Suppressions Prevent delivery to opted-out or unsafe recipients. - [`GET /suppressions`](/api/endpoints/suppressions/list-suppressions) — List suppressions. - [`POST /suppressions`](/api/endpoints/suppressions/create-suppressions) — Create suppressions. - [`GET /suppressions/{suppression_id}`](/api/endpoints/suppressions/retrieve-suppression) — Retrieve a suppression. - [`DELETE /suppressions/{suppression_id}`](/api/endpoints/suppressions/delete-suppression) — Delete a suppression. ## Pacing Control send rate, hours, and queue flow. - [`GET /pacing-rules`](/api/endpoints/pacing/list-pacing-rules) — List pacing rules. - [`POST /pacing-rules`](/api/endpoints/pacing/create-pacing-rule) — Create a pacing rule. - [`GET /pacing-rules/{rule_id}`](/api/endpoints/pacing/retrieve-pacing-rule) — Retrieve a pacing rule. - [`DELETE /pacing-rules/{rule_id}`](/api/endpoints/pacing/delete-pacing-rule) — Delete a pacing rule. - [`PATCH /pacing-rules/{rule_id}`](/api/endpoints/pacing/update-pacing-rule) — Update a pacing rule. - [`GET /pacing-rules/spread`](/api/endpoints/pacing/retrieve-pacing-spread) — Retrieve pacing spread. - [`PATCH /pacing-rules/spread`](/api/endpoints/pacing/update-pacing-spread) — Update pacing spread. - [`GET /pacing-queue`](/api/endpoints/pacing/retrieve-pacing-queue) — Retrieve the pacing queue. - [`POST /pacing-queue/release`](/api/endpoints/pacing/release-pacing-queue) — Release emails from the pacing queue. ## Workspace The workspace a request acts in: its name, and the defaults new domains start with. - [`GET /workspaces`](/api/endpoints/workspace/list-workspaces) — List workspaces. - [`GET /workspace`](/api/endpoints/workspace/retrieve-workspace) — Retrieve the workspace. - [`PATCH /workspace`](/api/endpoints/workspace/update-workspace) — Update the workspace. ## Members Who is in the workspace, what each of them may do, and the invitations waiting to be accepted. Admin only. - [`GET /members`](/api/endpoints/members/list-members) — List members. - [`DELETE /members/{member_id}`](/api/endpoints/members/remove-member) — Remove a member. - [`PATCH /members/{member_id}`](/api/endpoints/members/update-member) — Update a member. - [`GET /invitations`](/api/endpoints/members/list-invitations) — List invitations. - [`POST /invitations`](/api/endpoints/members/create-invitation) — Invite someone. - [`DELETE /invitations/{invitation_id}`](/api/endpoints/members/cancel-invitation) — Cancel an invitation. --- # Create an API key Source: https://docs.aiinbx.com/api/endpoints/api-keys/create-api-key Creates an organization-wide API key and returns its secret exactly once, in the `key` field. Store it before the response is discarded — it cannot be recovered. Choose the narrowest scope the caller needs: `read`, `sending`, or `full`. The key reaches the whole workspace, spaces included. Admin only. `POST /api-keys` --- # Delete an API key Source: https://docs.aiinbx.com/api/endpoints/api-keys/delete-api-key Deletes a key immediately. It authenticates nothing afterwards and cannot be recovered; issue a new key instead. Admin only. `DELETE /api-keys/{key_id}` --- # List API keys Source: https://docs.aiinbx.com/api/endpoints/api-keys/list-api-keys Lists the workspace's API keys, newest first. Keys are returned as metadata only — the prefix, scope, creation time, and `last_used_at`; the secret itself is never readable after creation. Admin only. `GET /api-keys` --- # Download an attachment Source: https://docs.aiinbx.com/api/endpoints/attachments/download-attachment Redirects to a short-lived signed URL for the attachment's original bytes. Follow the redirect; the signed URL expires, so resolve it on demand rather than storing it. `GET /attachments/{attachment_id}` --- # Inspect attachment metadata Source: https://docs.aiinbx.com/api/endpoints/attachments/inspect-attachment Returns the attachment's media type, size, and filename disposition in response headers without transferring the file — the cheap way to check a size before committing to a download. `HEAD /attachments/{attachment_id}` --- # Download prepared attachment text Source: https://docs.aiinbx.com/api/endpoints/attachments/retrieve-attachment-content Redirects to a short-lived signed URL for the attachment's prepared text — Markdown where the document has structure, plain text otherwise. Returns 404 `not_prepared` when the file type has no text to extract or preparation failed. `GET /attachments/{attachment_id}/content` --- # Create a domain Source: https://docs.aiinbx.com/api/endpoints/domains/create-domain Registers a sending domain and returns the DNS records to publish: SPF, DKIM, DMARC, a return path, and an MX record for receiving. `region` selects the regional mail infrastructure for this domain and cannot be changed afterwards. A wildcard — `*.acme.dev` — is verified once and covers every subdomain: the MX record goes at `*.acme.dev`, the rest at `acme.dev`, and the apex keeps whatever mail setup it has. A name one label under a wildcard of yours — `hi.acme.dev` under `*.acme.dev` — is created as a subdomain of it: no records, verified as soon as the wildcard is, in whatever `space_id` you give it. That is how a platform hands each customer an address of their own without touching DNS again. A domain name can be connected in several spaces and workspaces, but sending and receiving are enabled for the one whose DKIM key is published. To move them, add the domain where it should go and publish its DNS records. The next verification check moves them; existing mail stays where it was. Duplicate apex or wildcard identities within one space fail with `domain_taken`. Every workspace already has one domain it did not add: `.aiinbx.app`, listed with `provided: true`. It is verified through our zone, has no records and cannot be deleted; a name under `aiinbx.app` cannot be added by hand and fails with `reserved_domain`. A domain of its own counts against the plan's custom domains — a subdomain under a wildcard and the provided domain do not. With none left the request fails with 402 `allowance_reached`, and a workspace with no plan with 402 `plan_required`. `track_opens` and `track_clicks` set the domain's `tracking`; what they leave out starts as the workspace's tracking defaults in the console say — off unless they are set there — or, on a subdomain, as its wildcard's. Change either afterwards with `PATCH /domains/{domain_id}`. `POST /domains` --- # Delete a domain Source: https://docs.aiinbx.com/api/endpoints/domains/delete-domain Deletes a domain and stops future sends from it. Remove the published DNS records afterwards. A wildcard's subdomains are deleted with it, in whatever space they sit; a subdomain is removed on its own, with nothing to unpublish. The provided domain cannot be deleted and fails with `domain_provided`. `DELETE /domains/{domain_id}` --- # List domains Source: https://docs.aiinbx.com/api/endpoints/domains/list-domains Lists the workspace's sending domains with their verification state and tracking settings. `GET /domains` --- # Retrieve a domain Source: https://docs.aiinbx.com/api/endpoints/domains/retrieve-domain Returns one domain with its DNS records and the state of each — `pending`, `verified`, or `missing` — along with when each was last checked. `GET /domains/{domain_id}` --- # Diagnose domain DNS configuration Source: https://docs.aiinbx.com/api/endpoints/domains/retrieve-domain-diagnostics Reads the domain's live DNS zone and reports what is wrong with it — a duplicate SPF record, a permissive policy, a missing return path. Each finding carries a severity, an explanation, the fix, and the records it was drawn from. Nothing is stored; the result always reflects DNS as it is right now. `GET /domains/{domain_id}/diagnostics` --- # Update domain tracking settings Source: https://docs.aiinbx.com/api/endpoints/domains/update-domain Updates whether opens and clicks are tracked on mail sent from the domain. Applies to every send from it that does not say otherwise in `tracking`, from the next one to leave. At least one field is required. `PATCH /domains/{domain_id}` --- # Verify domain DNS records now Source: https://docs.aiinbx.com/api/endpoints/domains/verify-domain Checks the domain's DNS records against live DNS now. `verified_at` stays null until the sending identity’s DKIM verification succeeds; inbound MX, SPF, and DMARC readiness are separate. DNS propagation usually takes minutes and occasionally hours, so poll at a sane interval or subscribe to the `domain.verified` webhook instead. Domains are also rechecked in the background: a domain whose DKIM record stops resolving loses `verified_at` again and `domain.lost` is sent. `POST /domains/{domain_id}/verify` --- # Cancel an email Source: https://docs.aiinbx.com/api/endpoints/emails/cancel-email Cancels a scheduled email before it is composed and sent — its status becomes `canceled` — or discards a draft, which becomes `discarded`. Either is terminal: the email cannot be put back into flight. `POST /emails/{email_id}/cancel` --- # List emails Source: https://docs.aiinbx.com/api/endpoints/emails/list-emails Lists emails in the workspace, newest first. Filter by `direction`, delivery `status`, a single `thread_id`, or a literal `query`: every word in it must appear in the subject, the sender, a recipient or the Message-ID, in any order and case. The query is a literal filter; the API does not provide semantic email search. To sync, walk forward instead: `order=asc` with `after` set to the `created_at` of the last email you have lists only what is new, oldest first. `GET /emails` --- # Retrieve an email Source: https://docs.aiinbx.com/api/endpoints/emails/retrieve-email Returns one email in full: both bodies, every header, attachments, the delivery event history, and tracked engagements. Pass `include=attachment_content` to inline each attachment's prepared text, which saves a request per attachment before handing a message to a model. `GET /emails/{email_id}` --- # Send a draft Source: https://docs.aiinbx.com/api/endpoints/emails/send-draft Sends a draft: at the `scheduled_at` given, else at the draft's own while it is still ahead, else now. From here it is a `scheduled` email — counted against the plan, and composed again when it goes. Anything but a draft returns 409 `not_draft`; a workspace out of emails returns 402. `POST /emails/{email_id}/send` --- # Send an email Source: https://docs.aiinbx.com/api/endpoints/emails/send-email Sends an email — or, with `draft: true`, writes it for a person to review and send. Requires a `from` address on a verified domain or a connected mailbox, and at least one of `html` or `text`. `thread_id` continues a conversation; to answer a message AI Inbx has not seen — mail from before a migration, or from another provider — name it in `in_reply_to` and `references` instead. Recipients on a matching suppression list are dropped and reported in `suppressed`; a pacing rule that holds the message is reported in `pacing`. Pass `Idempotency-Key` so a retry after a timeout replays the original send instead of sending twice. A workspace with no plan fails with 402 `plan_required`, and one that has used its plan's emails for the month with 402 `allowance_reached`. `POST /emails` --- # Update an email Source: https://docs.aiinbx.com/api/endpoints/emails/update-email Changes an email that has not gone out — a `draft` or a `scheduled` one: its recipients, subject, bodies, attachments or send time. Fields left out stay as they are. The email is composed again when it goes, so what is sent is what it says by then. One that has begun sending, or was canceled or discarded, returns 409 `not_scheduled`. `PATCH /emails/{email_id}` --- # List events Source: https://docs.aiinbx.com/api/endpoints/events/list-events Lists the workspace's events, newest first — every event, recorded when it happens, whether or not a webhook endpoint subscribes to its type. Each is the envelope a webhook delivers, with the same `id`, so a handler that deduplicates on it can read from here and from its endpoint alike. Filter by `type`, repeated for any of several, or by `email_id` for what happened to one email. To catch up after missed webhooks, walk forward: `order=asc` with `after` set to the `created_at` of the last event you processed. `data` is the summary every endpoint receives; the `data.email` a `full` endpoint is sent is read when a delivery goes out and not kept, so read the email by its `email_id`. Test events sent to an endpoint are not listed. `GET /events` --- # Retrieve an event Source: https://docs.aiinbx.com/api/endpoints/events/retrieve-event Returns one event by id — the `id` of the envelope a webhook delivered, which is also the `AIInbx-Event-ID` header and a delivery's `event_id`. `GET /events/{event_id}` --- # Create a mailbox connection URL Source: https://docs.aiinbx.com/api/endpoints/mailboxes/connect-mailbox Creates a single-use, short-lived URL that walks a customer through authorizing their Gmail or Outlook mailbox. Redirect them to it rather than emailing it. Pass `ref` — your own identifier — and `metadata` for anything else you want kept with the mailbox; both are stored on it and carried on every `mailbox.*` webhook. On a reconnect each replaces what the mailbox had, and one left out leaves it alone. The `mailbox.connected` webhook — not the browser returning to `return_to` — is the authoritative signal that the mailbox is live. `return_to` may be any URL here, since the request is authenticated; a connect link opened from a browser is held to the app's `return_urls` instead. `space_id` files the mailbox in a space; the returned URL carries it, so a platform mints one link per customer server-side rather than handing out the bare hosted link. A workspace with no plan fails with 402 `plan_required`. A mailbox counts against the plan's mailboxes, but which one it will be is only known once the person has authorized: with none left, a mailbox the workspace does not already hold is refused then, and the refusal is reported in `error` on `return_to`. Reconnecting one that is `active` or `needs_reauth` takes nothing new. `POST /mailboxes/connect` --- # Disconnect a mailbox Source: https://docs.aiinbx.com/api/endpoints/mailboxes/disconnect-mailbox Disconnects a mailbox, stopping sync and dropping its stored credentials. Messages already received stay on their threads. `DELETE /mailboxes/{mailbox_id}` --- # List mailboxes Source: https://docs.aiinbx.com/api/endpoints/mailboxes/list-mailboxes Lists connected Gmail and Outlook mailboxes with their sync state. `GET /mailboxes` --- # Retrieve a mailbox Source: https://docs.aiinbx.com/api/endpoints/mailboxes/retrieve-mailbox Returns one mailbox, including its `state` and the provider's `state_reason` when there is one. A mailbox that is not `active` cannot send. `GET /mailboxes/{mailbox_id}` --- # Queue a mailbox sync Source: https://docs.aiinbx.com/api/endpoints/mailboxes/sync-mailbox Queues a catch-up sync for a mailbox. Mail normally arrives on its own through provider push notifications, so this is a repair tool rather than a way to poll. Messages found surface as ordinary `email.received` events. `POST /mailboxes/{mailbox_id}/sync` --- # Cancel an invitation Source: https://docs.aiinbx.com/api/endpoints/members/cancel-invitation Cancels an invitation that is waiting to be accepted; the link in the mail stops working. Send a new one if they still need it. Admin only. `DELETE /invitations/{invitation_id}` --- # Invite someone Source: https://docs.aiinbx.com/api/endpoints/members/create-invitation Mails an invitation to join the workspace, with a link that is good for seven days. Inviting an address that already has one waiting replaces it once the new mail has gone — the earlier link then stops working — which is also how an invitation is sent again. An address that is already a member fails with 409 `already_member`. When the mail cannot go, nothing is created and any earlier invitation keeps working: the address has been invited too often today, or the inviter has sent too many, fails with 429 `invitation_not_sent` — try again later; an address that asked not to hear from us fails with 400 `recipients_suppressed`, which will not change on retrying. Invitations sent with an API key are in the name of the person who created the key, or the owner once they are gone. Admin only. `POST /invitations` --- # List invitations Source: https://docs.aiinbx.com/api/endpoints/members/list-invitations Lists the invitations nobody has answered, newest first — lapsed ones too, past their `expires_at`: those can no longer be accepted, and inviting the address again sends a fresh one. Admin only. `GET /invitations` --- # List members Source: https://docs.aiinbx.com/api/endpoints/members/list-members Lists everyone in the workspace, earliest to join first, with their role and when they were last active. A workspace holds at most 100 members, so the list is never paged. Admin only. `GET /members` --- # Remove a member Source: https://docs.aiinbx.com/api/endpoints/members/remove-member Takes a member's access away at once. The mail they sent and the API keys they created stay with the workspace. The owner cannot be removed (409 `owner_protected`). Admin only. `DELETE /members/{member_id}` --- # Update a member Source: https://docs.aiinbx.com/api/endpoints/members/update-member Changes what a member may do: `admin` manages the workspace, its members and its keys; `member` works with mail. It takes effect on their next request. The owner's role is not changed here — 409 `owner_protected` — the workspace changes hands by a transfer, in the console. Admin only. `PATCH /members/{member_id}` --- # Create an OAuth app Source: https://docs.aiinbx.com/api/endpoints/oauth-apps/create-o-auth-app Registers your own OAuth app so the mailbox consent screen carries your product's name rather than AI Inbx. The response returns the `redirect_uri` to register with the provider, a hosted `connect_url`, and — for Google — the `push_endpoint` your own Pub/Sub topic should publish to. The `slug` is claimed globally because it forms the connect URL. `return_urls` lists the pages of yours a connect link (`connect_url` + `/start?return_to=…`) may send a person back to; without one, only the hosted page works. `POST /oauth-apps` --- # Delete an OAuth app Source: https://docs.aiinbx.com/api/endpoints/oauth-apps/delete-o-auth-app Deletes an OAuth app. Mailboxes already connected through it keep working until their authorization lapses. `DELETE /oauth-apps/{app_id}` --- # List OAuth apps Source: https://docs.aiinbx.com/api/endpoints/oauth-apps/list-o-auth-apps Lists the workspace's own Google and Microsoft OAuth apps. `GET /oauth-apps` --- # Retrieve an OAuth app Source: https://docs.aiinbx.com/api/endpoints/oauth-apps/retrieve-o-auth-app Returns one OAuth app. The client secret is never returned. `GET /oauth-apps/{app_id}` --- # Update an OAuth app Source: https://docs.aiinbx.com/api/endpoints/oauth-apps/update-o-auth-app Updates an OAuth app's credentials, branding or return URLs. At least one field is required. A rotated secret replaces the old one immediately, so update the provider first. `return_urls` replaces the whole list. `PATCH /oauth-apps/{app_id}` --- # Create a pacing rule Source: https://docs.aiinbx.com/api/endpoints/pacing/create-pacing-rule Creates a pacing rule. An `hours` rule holds mail outside the weekly windows you declare, evaluated in the rule's own timezone. A `limit` rule caps sends per rolling window against a scope — the rule as a whole, or per sender address, sending domain, recipient, or recipient domain. An empty `match` array applies the rule to every send. `space_id` makes the rule read one space's mail alone; workspace rules apply to every space and stack on top. An enabled rule counts against the plan's active custom pacing rules: with none left the request fails with 402 `allowance_reached`, and a workspace with no plan with 402 `plan_required`. A rule created with `enabled` false takes nothing until it is switched on. `POST /pacing-rules` --- # Delete a pacing rule Source: https://docs.aiinbx.com/api/endpoints/pacing/delete-pacing-rule Deletes a pacing rule. Messages it was holding become eligible to send as soon as the remaining rules allow. A `builtin` rule cannot be deleted and fails with `rule_builtin`. `DELETE /pacing-rules/{rule_id}` --- # List pacing rules Source: https://docs.aiinbx.com/api/endpoints/pacing/list-pacing-rules Lists the workspace's pacing rules, both sending-hours and rate-limit kinds. Rules with `builtin: true` came with the workspace: they cap mail sent from the [provided domain](/guides/domains#your-provided-domain) and cannot be changed or removed. `GET /pacing-rules` --- # Release emails from the pacing queue Source: https://docs.aiinbx.com/api/endpoints/pacing/release-pacing-queue Releases up to 500 held emails immediately. `count_toward_limits` defaults to true; setting it to false means the sends do not consume rule budget, which makes the rule under-count — reserve it for genuinely exceptional releases. For mail that should never queue, set `pacing.skip` on the send instead. `POST /pacing-queue/release` --- # Retrieve the pacing queue Source: https://docs.aiinbx.com/api/endpoints/pacing/retrieve-pacing-queue Returns a snapshot of everything pacing is currently holding: a sample of queued messages, the rules in effect, and per-rule counts of how many messages each matched and how many it is holding. The per-rule counts are the fastest way to identify which rule is responsible. `GET /pacing-queue` --- # Retrieve a pacing rule Source: https://docs.aiinbx.com/api/endpoints/pacing/retrieve-pacing-rule Returns one pacing rule with its match patterns and its schedule or limit. `GET /pacing-rules/{rule_id}` --- # Retrieve pacing spread Source: https://docs.aiinbx.com/api/endpoints/pacing/retrieve-pacing-spread Returns the workspace's send-timing spread, a value from 0 to 100. `GET /pacing-rules/spread` --- # Update a pacing rule Source: https://docs.aiinbx.com/api/endpoints/pacing/update-pacing-rule Updates a pacing rule. At least one field is required. Setting `enabled` to false parks a rule without losing its configuration, which is the quickest way to confirm which rule is holding mail. A `builtin` rule cannot be changed and fails with `rule_builtin`. Setting `enabled` to true on a parked rule takes one of the plan's active custom pacing rules again, and fails with 402 `allowance_reached` when none is left. `PATCH /pacing-rules/{rule_id}` --- # Update pacing spread Source: https://docs.aiinbx.com/api/endpoints/pacing/update-pacing-spread Sets how much randomness is added to send timing. At 0 a rate-limited stream goes out on a metronome; higher values vary the gaps, costing a little throughput in exchange for traffic that does not look machine-generated. Applies to limit rules. `PATCH /pacing-rules/spread` --- # Create a space Source: https://docs.aiinbx.com/api/endpoints/spaces/create-space Creates a space — one per customer, typically. Domains, mailboxes, rules and suppressions are put in a space with `space_id` when they are created, and every email and thread inherits the space of the domain or mailbox it went through. Anything created without a `space_id` belongs to the workspace itself and `space_id` reads as null. API keys and webhook endpoints belong to the workspace. `external_id` is your own id for the customer: unique per workspace, so a second space for the same customer is `409 external_id_taken`, and the space can be found by it with `GET /spaces?external_id=`. `POST /spaces` --- # Delete a space Source: https://docs.aiinbx.com/api/endpoints/spaces/delete-space Marks the space for deletion and starts its teardown in the background. The space immediately stops accepting work and no longer appears in the API; its domains then come off DNS verification and sending, its mailboxes are disconnected, and its emails, threads, rules and suppressions are removed. A wildcard domain in the space is deleted with its subdomains, including any filed in other spaces. Admin only. `DELETE /spaces/{space_id}` --- # List spaces Source: https://docs.aiinbx.com/api/endpoints/spaces/list-spaces Lists the workspace's spaces, oldest first. Filter by `external_id` to find the one that stands for a customer of yours. `GET /spaces` --- # Retrieve a space Source: https://docs.aiinbx.com/api/endpoints/spaces/retrieve-space Returns one space by id, with its name and the `external_id` you gave it. `GET /spaces/{space_id}` --- # Update a space Source: https://docs.aiinbx.com/api/endpoints/spaces/update-space Changes the space's name or `external_id`; only the fields given change, and `external_id: null` clears it. Nothing in the space moves. `PATCH /spaces/{space_id}` --- # Create suppressions Source: https://docs.aiinbx.com/api/endpoints/suppressions/create-suppressions Adds up to 1000 addresses to a suppression list. `key` defaults to the workspace-wide `*` list and `scope` to `all`; a `scope` of `optional` blocks only sends marked as unsubscribable, so a marketing opt-out does not stop a password reset. Adding an address that is already listed updates the existing entry rather than duplicating it, and never narrows a wider scope. `space_id` puts the entries on a space's list, which stops that space's sends alone; without it they stop every space's. `POST /suppressions` --- # Delete a suppression Source: https://docs.aiinbx.com/api/endpoints/suppressions/delete-suppression Removes a suppression entry, allowing sends to that address again. Removing a `bounce` or `complaint` entry means mailing an address that already rejected you or reported you as spam — do it only with specific evidence the address was fixed. `DELETE /suppressions/{suppression_id}` --- # List suppressions Source: https://docs.aiinbx.com/api/endpoints/suppressions/list-suppressions Lists suppression entries, filterable by list `key`, `reason`, or a substring of the `address`. `blocks` and `last_blocked_at` show how often each entry has actually stopped a send. `GET /suppressions` --- # Retrieve a suppression Source: https://docs.aiinbx.com/api/endpoints/suppressions/retrieve-suppression Returns one suppression entry, including how it was created and how many sends it has stopped. `GET /suppressions/{suppression_id}` --- # Forward a thread Source: https://docs.aiinbx.com/api/endpoints/threads/forward-thread Sends the whole thread as one email to recipients who were not on it. Every message is rendered into one transcript, oldest first, each turn as what its author wrote with quoted tails and repeated signatures removed; the thread's attachments ride along unless `include_attachments` is false, and `note` is placed above the transcript. Only `to` is required: the sender defaults to the thread's mailbox and the subject to `Fwd:` and the thread's. The forward opens a thread of its own, linked back through `forward_of`, so a later reply on the original still goes to its participants and replies to the forward land on the forward. Suppression, pacing, scheduling, and idempotency behave exactly as on a send. So does the plan: 402 `plan_required` without one, 402 `allowance_reached` once its emails are used up. `POST /threads/{thread_id}/forward` --- # List threads Source: https://docs.aiinbx.com/api/endpoints/threads/list-threads Lists conversations, most recently active first. Every word of `query` must appear in the subject, the mailbox or a participant's address, literally and in any order; `mailbox` narrows to one address. `GET /threads` --- # Reply in a thread Source: https://docs.aiinbx.com/api/endpoints/threads/reply-to-thread Replies within a thread. The sender, recipients, subject, and the `In-Reply-To` and `References` headers are inferred from the conversation, so only the content is required — set `reply_all` or the individual fields to override what is inferred. Suppression, pacing, and idempotency behave exactly as on a send. So does the plan: 402 `plan_required` without one, 402 `allowance_reached` once its emails are used up. `POST /threads/{thread_id}/reply` --- # Retrieve a thread Source: https://docs.aiinbx.com/api/endpoints/threads/retrieve-thread Returns a thread with its messages inline, oldest first. Messages paginate independently of the thread list via `message_limit` and `message_cursor`, so a long conversation can be walked without loading it whole. `GET /threads/{thread_id}` --- # domain.lost Source: https://docs.aiinbx.com/api/endpoints/webhook-events/domain-lost A verified domain's DKIM record stopped resolving. `POST domain.lost` **Webhook.** The API sends this request to your endpoint. --- # domain.verified Source: https://docs.aiinbx.com/api/endpoints/webhook-events/domain-verified A domain's DKIM identity was verified, and the domain can send. `POST domain.verified` **Webhook.** The API sends this request to your endpoint. --- # email.bounced Source: https://docs.aiinbx.com/api/endpoints/webhook-events/email-bounced Delivery to one or more recipients failed; a hard bounce writes a suppression. `POST email.bounced` **Webhook.** The API sends this request to your endpoint. --- # email.clicked Source: https://docs.aiinbx.com/api/endpoints/webhook-events/email-clicked A tracked link was clicked, with bot and scanner hits flagged. `POST email.clicked` **Webhook.** The API sends this request to your endpoint. --- # email.complained Source: https://docs.aiinbx.com/api/endpoints/webhook-events/email-complained A recipient marked the message as spam, which weighs on sending reputation. `POST email.complained` **Webhook.** The API sends this request to your endpoint. --- # email.delivered Source: https://docs.aiinbx.com/api/endpoints/webhook-events/email-delivered The receiving server accepted the message, reported per recipient. `POST email.delivered` **Webhook.** The API sends this request to your endpoint. --- # email.failed Source: https://docs.aiinbx.com/api/endpoints/webhook-events/email-failed The mail provider refused the message before any delivery attempt. `POST email.failed` **Webhook.** The API sends this request to your endpoint. --- # email.opened Source: https://docs.aiinbx.com/api/endpoints/webhook-events/email-opened A tracked open was recorded, with bot and privacy-proxy hits flagged. `POST email.opened` **Webhook.** The API sends this request to your endpoint. --- # email.received Source: https://docs.aiinbx.com/api/endpoints/webhook-events/email-received Inbound mail arrived and was matched onto a thread, once per received message. `POST email.received` **Webhook.** The API sends this request to your endpoint. --- # email.sent Source: https://docs.aiinbx.com/api/endpoints/webhook-events/email-sent A message was handed to the mail provider: acceptance, not delivery. `POST email.sent` **Webhook.** The API sends this request to your endpoint. --- # email.unsubscribed Source: https://docs.aiinbx.com/api/endpoints/webhook-events/email-unsubscribed A recipient opted out by link, one-click header, or reply. `POST email.unsubscribed` **Webhook.** The API sends this request to your endpoint. --- # mailbox.connected Source: https://docs.aiinbx.com/api/endpoints/webhook-events/mailbox-connected A customer finished authorizing a Gmail or Outlook mailbox. `POST mailbox.connected` **Webhook.** The API sends this request to your endpoint. --- # mailbox.disconnected Source: https://docs.aiinbx.com/api/endpoints/webhook-events/mailbox-disconnected A mailbox was removed, by you or by the customer revoking access. `POST mailbox.disconnected` **Webhook.** The API sends this request to your endpoint. --- # mailbox.needs_reauth Source: https://docs.aiinbx.com/api/endpoints/webhook-events/mailbox-needs-reauth A mailbox's stored authorization stopped working. `POST mailbox.needs_reauth` **Webhook.** The API sends this request to your endpoint. --- # thread.created Source: https://docs.aiinbx.com/api/endpoints/webhook-events/thread-created A new conversation started: an inbound message, a send, or a forward. `POST thread.created` **Webhook.** The API sends this request to your endpoint. --- # Create a webhook endpoint Source: https://docs.aiinbx.com/api/endpoints/webhooks/create-webhook-endpoint Registers an organization-wide endpoint and returns its signing secret exactly once, in the `secret` field: no later read shows it again. A secret that was lost, or has leaked, is replaced with `POST /webhook-endpoints/{endpoint_id}/rotate-secret`, which keeps the old one verifying for a grace period while you deploy the new one. `subscriptions` must name at least one event type. Setting `payload` to `full` puts the whole email on `email.received` and `email.sent`, as `data.email`, so a handler does not have to fetch it. Optional routing rules narrow delivery by sender or recipient: a matching `block` rule always wins, and an empty allow list means no opinion. The endpoint receives every space's events, each stamped with its `space_id`. `POST /webhook-endpoints` --- # Delete a webhook endpoint Source: https://docs.aiinbx.com/api/endpoints/webhooks/delete-webhook-endpoint Deletes an endpoint. Pending deliveries to it stop. `DELETE /webhook-endpoints/{endpoint_id}` --- # List webhook deliveries Source: https://docs.aiinbx.com/api/endpoints/webhooks/list-webhook-deliveries Lists deliveries to an endpoint, filterable by state. Each carries the event envelope it sends and every attempt made: timestamp, status code, duration, error, and the beginning of your response, which is usually what explains a rejection. `body` is what is stored. For a `full` endpoint that is the envelope without `data.email`: the email is read from the message each time a delivery is sent and is not kept with it. It is null for a `v1` endpoint — its legacy body is built from the message at send time, not stored — and for a delivery nothing was sent for. `GET /webhook-endpoints/{endpoint_id}/deliveries` --- # List webhook endpoints Source: https://docs.aiinbx.com/api/endpoints/webhooks/list-webhook-endpoints Lists the workspace's webhook endpoints with their subscriptions and routing rules. `GET /webhook-endpoints` --- # Retrieve a webhook endpoint Source: https://docs.aiinbx.com/api/endpoints/webhooks/retrieve-webhook-endpoint Returns one endpoint, including when a rotated previous secret stops being accepted. `GET /webhook-endpoints/{endpoint_id}` --- # Retry webhook deliveries Source: https://docs.aiinbx.com/api/endpoints/webhooks/retry-webhook-deliveries Replays up to 100 deliveries. A replay carries the same event `id` as the original, so a handler that deduplicates on it stays correct. `POST /webhook-endpoints/{endpoint_id}/deliveries/retry` --- # Rotate a webhook signing secret Source: https://docs.aiinbx.com/api/endpoints/webhooks/rotate-webhook-secret Issues a new signing secret and returns it, once — the only way to get a secret after the endpoint was created. The previous one keeps verifying for `grace_seconds` (a day by default, a week at most): every delivery in that window is signed with both, so a deployment can roll over without dropping events, and `previous_secret_expires_at` says when the overlap ends. Set the grace period to 0 only when a secret has leaked and the exposure matters more than the gap. `POST /webhook-endpoints/{endpoint_id}/rotate-secret` --- # Send a test webhook Source: https://docs.aiinbx.com/api/endpoints/webhooks/test-webhook-endpoint Delivers a synthetic event to the endpoint and reports what it actually did — status code, duration, error, and the first 2 KB of its response. The test event is signed like a real one, so it exercises signature verification too. `payload` is sent verbatim and does not have to match the real shape for that event type. A test event is about no message, so on a `full` endpoint the `data.email` of an `email.received` or `email.sent` test is the `email` you put in `payload`, or null. `POST /webhook-endpoints/{endpoint_id}/test` --- # Update a webhook endpoint Source: https://docs.aiinbx.com/api/endpoints/webhooks/update-webhook-endpoint Updates an endpoint's URL, subscriptions, routing rules, payload, or enabled state. At least one field is required. A change of `payload` applies from the next delivery attempt, retries of earlier events included; a `v1` endpoint cannot be `full`. A disabled endpoint receives nothing, and events that occur while it is off are not queued for later. `PATCH /webhook-endpoints/{endpoint_id}` --- # List workspaces Source: https://docs.aiinbx.com/api/endpoints/workspace/list-workspaces Lists the workspaces the caller can act in, with its role in each. An API key reaches its own workspace alone. An OAuth token reaches every workspace it was granted, and a request with one that reaches several names the workspace it acts in with the `AIInbx-Workspace` header, set to an `id` from here; this list is the one call that needs no header. `mode` says whether the caller acts as the whole of its workspaces or as an inbox; a token connected as an inbox reaches the workspaces of its inboxes, and `inboxes` names the addresses it reads and sends as. `GET /workspaces` --- # Retrieve the workspace Source: https://docs.aiinbx.com/api/endpoints/workspace/retrieve-workspace Returns the workspace the request acts in: its name, its slug, and the tracking defaults a domain added from now on starts with. `GET /workspace` --- # Update the workspace Source: https://docs.aiinbx.com/api/endpoints/workspace/update-workspace Renames the workspace or changes its tracking defaults; only the fields given change. A new name brings a new slug, which moves the console URLs and the provided domain's name with it, so a workspace can be renamed once a month — sooner fails with 409 `rename_cooldown`. Tracking defaults apply to domains added from now on; each existing domain keeps its own. Admin only. `PATCH /workspace` --- # Events API Source: https://docs.aiinbx.com/api/events {/* Generated by scripts/openapi.ts from the shared API contract. */} Read back what happened in the workspace — the events webhooks carry, whether or not an endpoint heard them. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List events](/api/endpoints/events/list-events) | `/events` | | `GET` | [Retrieve an event](/api/endpoints/events/retrieve-event) | `/events/{event_id}` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Mailboxes API Source: https://docs.aiinbx.com/api/mailboxes {/* Generated by scripts/openapi.ts from the shared API contract. */} Connect and manage provider mailboxes. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List mailboxes](/api/endpoints/mailboxes/list-mailboxes) | `/mailboxes` | | `POST` | [Create a mailbox connection URL](/api/endpoints/mailboxes/connect-mailbox) | `/mailboxes/connect` | | `GET` | [Retrieve a mailbox](/api/endpoints/mailboxes/retrieve-mailbox) | `/mailboxes/{mailbox_id}` | | `DELETE` | [Disconnect a mailbox](/api/endpoints/mailboxes/disconnect-mailbox) | `/mailboxes/{mailbox_id}` | | `POST` | [Queue a mailbox sync](/api/endpoints/mailboxes/sync-mailbox) | `/mailboxes/{mailbox_id}/sync` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Members API Source: https://docs.aiinbx.com/api/members {/* Generated by scripts/openapi.ts from the shared API contract. */} Who is in the workspace, what each of them may do, and the invitations waiting to be accepted. Admin only. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List members](/api/endpoints/members/list-members) | `/members` | | `DELETE` | [Remove a member](/api/endpoints/members/remove-member) | `/members/{member_id}` | | `PATCH` | [Update a member](/api/endpoints/members/update-member) | `/members/{member_id}` | | `GET` | [List invitations](/api/endpoints/members/list-invitations) | `/invitations` | | `POST` | [Invite someone](/api/endpoints/members/create-invitation) | `/invitations` | | `DELETE` | [Cancel an invitation](/api/endpoints/members/cancel-invitation) | `/invitations/{invitation_id}` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # OAuth Apps API Source: https://docs.aiinbx.com/api/oauth-apps {/* Generated by scripts/openapi.ts from the shared API contract. */} Manage customer-owned Google and Microsoft OAuth apps. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List OAuth apps](/api/endpoints/oauth-apps/list-o-auth-apps) | `/oauth-apps` | | `POST` | [Create an OAuth app](/api/endpoints/oauth-apps/create-o-auth-app) | `/oauth-apps` | | `GET` | [Retrieve an OAuth app](/api/endpoints/oauth-apps/retrieve-o-auth-app) | `/oauth-apps/{app_id}` | | `DELETE` | [Delete an OAuth app](/api/endpoints/oauth-apps/delete-o-auth-app) | `/oauth-apps/{app_id}` | | `PATCH` | [Update an OAuth app](/api/endpoints/oauth-apps/update-o-auth-app) | `/oauth-apps/{app_id}` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Pacing API Source: https://docs.aiinbx.com/api/pacing {/* Generated by scripts/openapi.ts from the shared API contract. */} Control send rate, hours, and queue flow. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List pacing rules](/api/endpoints/pacing/list-pacing-rules) | `/pacing-rules` | | `POST` | [Create a pacing rule](/api/endpoints/pacing/create-pacing-rule) | `/pacing-rules` | | `GET` | [Retrieve a pacing rule](/api/endpoints/pacing/retrieve-pacing-rule) | `/pacing-rules/{rule_id}` | | `DELETE` | [Delete a pacing rule](/api/endpoints/pacing/delete-pacing-rule) | `/pacing-rules/{rule_id}` | | `PATCH` | [Update a pacing rule](/api/endpoints/pacing/update-pacing-rule) | `/pacing-rules/{rule_id}` | | `GET` | [Retrieve pacing spread](/api/endpoints/pacing/retrieve-pacing-spread) | `/pacing-rules/spread` | | `PATCH` | [Update pacing spread](/api/endpoints/pacing/update-pacing-spread) | `/pacing-rules/spread` | | `GET` | [Retrieve the pacing queue](/api/endpoints/pacing/retrieve-pacing-queue) | `/pacing-queue` | | `POST` | [Release emails from the pacing queue](/api/endpoints/pacing/release-pacing-queue) | `/pacing-queue/release` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Spaces API Source: https://docs.aiinbx.com/api/spaces {/* Generated by scripts/openapi.ts from the shared API contract. */} Group a workspace's domains, mailboxes and mail by customer. Optional: a workspace that is not a platform never needs one. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List spaces](/api/endpoints/spaces/list-spaces) | `/spaces` | | `POST` | [Create a space](/api/endpoints/spaces/create-space) | `/spaces` | | `GET` | [Retrieve a space](/api/endpoints/spaces/retrieve-space) | `/spaces/{space_id}` | | `DELETE` | [Delete a space](/api/endpoints/spaces/delete-space) | `/spaces/{space_id}` | | `PATCH` | [Update a space](/api/endpoints/spaces/update-space) | `/spaces/{space_id}` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Suppressions API Source: https://docs.aiinbx.com/api/suppressions {/* Generated by scripts/openapi.ts from the shared API contract. */} Prevent delivery to opted-out or unsafe recipients. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List suppressions](/api/endpoints/suppressions/list-suppressions) | `/suppressions` | | `POST` | [Create suppressions](/api/endpoints/suppressions/create-suppressions) | `/suppressions` | | `GET` | [Retrieve a suppression](/api/endpoints/suppressions/retrieve-suppression) | `/suppressions/{suppression_id}` | | `DELETE` | [Delete a suppression](/api/endpoints/suppressions/delete-suppression) | `/suppressions/{suppression_id}` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Threads API Source: https://docs.aiinbx.com/api/threads {/* Generated by scripts/openapi.ts from the shared API contract. */} Read email conversations. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List threads](/api/endpoints/threads/list-threads) | `/threads` | | `GET` | [Retrieve a thread](/api/endpoints/threads/retrieve-thread) | `/threads/{thread_id}` | | `POST` | [Reply in a thread](/api/endpoints/threads/reply-to-thread) | `/threads/{thread_id}/reply` | | `POST` | [Forward a thread](/api/endpoints/threads/forward-thread) | `/threads/{thread_id}/forward` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Webhook events Source: https://docs.aiinbx.com/api/webhook-events {/* Generated by scripts/openapi.ts from the shared API contract. */} What an endpoint receives: one request per event, each signed, in the envelope every event shares. ## Events | Event | Fires when | | --- | --- | | [`email.received`](/api/endpoints/webhook-events/email-received) | Inbound mail arrived and was matched onto a thread, once per received message. | | [`email.sent`](/api/endpoints/webhook-events/email-sent) | A message was handed to the mail provider: acceptance, not delivery. | | [`email.delivered`](/api/endpoints/webhook-events/email-delivered) | The receiving server accepted the message, reported per recipient. | | [`email.bounced`](/api/endpoints/webhook-events/email-bounced) | Delivery to one or more recipients failed; a hard bounce writes a suppression. | | [`email.complained`](/api/endpoints/webhook-events/email-complained) | A recipient marked the message as spam, which weighs on sending reputation. | | [`email.failed`](/api/endpoints/webhook-events/email-failed) | The mail provider refused the message before any delivery attempt. | | [`email.unsubscribed`](/api/endpoints/webhook-events/email-unsubscribed) | A recipient opted out by link, one-click header, or reply. | | [`email.opened`](/api/endpoints/webhook-events/email-opened) | A tracked open was recorded, with bot and privacy-proxy hits flagged. | | [`email.clicked`](/api/endpoints/webhook-events/email-clicked) | A tracked link was clicked, with bot and scanner hits flagged. | | [`thread.created`](/api/endpoints/webhook-events/thread-created) | A new conversation started: an inbound message, a send, or a forward. | | [`domain.verified`](/api/endpoints/webhook-events/domain-verified) | A domain's DKIM identity was verified, and the domain can send. | | [`domain.lost`](/api/endpoints/webhook-events/domain-lost) | A verified domain's DKIM record stopped resolving. | | [`mailbox.connected`](/api/endpoints/webhook-events/mailbox-connected) | A customer finished authorizing a Gmail or Outlook mailbox. | | [`mailbox.needs_reauth`](/api/endpoints/webhook-events/mailbox-needs-reauth) | A mailbox's stored authorization stopped working. | | [`mailbox.disconnected`](/api/endpoints/webhook-events/mailbox-disconnected) | A mailbox was removed, by you or by the customer revoking access. | Check each delivery's signature before trusting it: see [Verifying](/webhooks/verifying). --- # Webhooks API Source: https://docs.aiinbx.com/api/webhooks {/* Generated by scripts/openapi.ts from the shared API contract. */} Configure event delivery and inspect delivery attempts. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List webhook endpoints](/api/endpoints/webhooks/list-webhook-endpoints) | `/webhook-endpoints` | | `POST` | [Create a webhook endpoint](/api/endpoints/webhooks/create-webhook-endpoint) | `/webhook-endpoints` | | `GET` | [Retrieve a webhook endpoint](/api/endpoints/webhooks/retrieve-webhook-endpoint) | `/webhook-endpoints/{endpoint_id}` | | `DELETE` | [Delete a webhook endpoint](/api/endpoints/webhooks/delete-webhook-endpoint) | `/webhook-endpoints/{endpoint_id}` | | `PATCH` | [Update a webhook endpoint](/api/endpoints/webhooks/update-webhook-endpoint) | `/webhook-endpoints/{endpoint_id}` | | `POST` | [Rotate a webhook signing secret](/api/endpoints/webhooks/rotate-webhook-secret) | `/webhook-endpoints/{endpoint_id}/rotate-secret` | | `POST` | [Send a test webhook](/api/endpoints/webhooks/test-webhook-endpoint) | `/webhook-endpoints/{endpoint_id}/test` | | `GET` | [List webhook deliveries](/api/endpoints/webhooks/list-webhook-deliveries) | `/webhook-endpoints/{endpoint_id}/deliveries` | | `POST` | [Retry webhook deliveries](/api/endpoints/webhooks/retry-webhook-deliveries) | `/webhook-endpoints/{endpoint_id}/deliveries/retry` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Workspace API Source: https://docs.aiinbx.com/api/workspace {/* Generated by scripts/openapi.ts from the shared API contract. */} The workspace a request acts in: its name, and the defaults new domains start with. ## Endpoints | Method | Operation | Path | | --- | --- | --- | | `GET` | [List workspaces](/api/endpoints/workspace/list-workspaces) | `/workspaces` | | `GET` | [Retrieve the workspace](/api/endpoints/workspace/retrieve-workspace) | `/workspace` | | `PATCH` | [Update the workspace](/api/endpoints/workspace/update-workspace) | `/workspace` | ## Request essentials [#request-essentials] Use `https://api.aiinbx.com/api/v2` as the base URL and send your API key in `Authorization: Bearer `. Keep credentials on your server. See [Authentication](/authentication) for scopes, [Conventions](/reference/conventions) for pagination and idempotency, and [Errors](/reference/errors) for recovery guidance. Each endpoint page includes its parameters, response schemas, and copyable TypeScript SDK, Python SDK, and curl examples. --- # Authentication Source: https://docs.aiinbx.com/authentication Every request from your code carries an API key as a bearer token: ```bash curl https://api.aiinbx.com/api/v2/threads \ -H "Authorization: Bearer $AI_INBX_API_KEY" ``` Both SDKs read `AI_INBX_API_KEY` from the environment, so the common case needs no argument: ```ts TypeScript import AIInbx from "aiinbx" const aiinbx = new AIInbx() // or new AIInbx({ apiKey: "..." }) ``` ```python Python from aiinbx import AIInbx with AIInbx() as client: # or AIInbx(api_key="...") ... ``` A key belongs to one workspace, reaches every [space](/guides/spaces) in it, and can never cross into another workspace. Keys are for your servers; a customer who needs the API goes through your product, never through AI Inbx directly. ## Signed-in clients The [CLI](/cli) and the [MCP server](/mcp) sign in with your account instead of a key. You pick the access and the workspaces on the consent page, or make the connection an [inbox](/guides/agent-inbox). They send the access token they get as the same bearer token. A token that reaches several workspaces names the one a request acts in with `AIInbx-Workspace: `; `GET /workspaces` lists them, and a request without it gets `400` [`workspace_required`](/reference/errors#workspace_required). ## Base URL ``` https://api.aiinbx.com/api/v2 ``` Both [SDKs](/sdks) default to it. Override with `baseURL` (TypeScript) or `base_url` (Python) when you're pointing at a local instance. :::warning[Missing or invalid keys] A request with no `Authorization` header, a malformed one, or a deleted key gets `401` with the code [`unauthorized`](/reference/errors#unauthorized) and a `WWW-Authenticate: Bearer` header. A valid key that lacks the scope for the operation gets `403` [`forbidden`](/reference/errors#forbidden) — a different failure, and one retrying won't fix. ::: ## Scopes A key is created with one of three scopes. `full` satisfies every requirement; the other two are deliberate narrowings for keys that live somewhere you'd rather not put a `full` key. | Prop | Type | Default | Description | | - | - | - | - | | `full` | `scope` | - | Everything. Required for anything that changes configuration — keys, domains, mailboxes, OAuth apps, webhook endpoints, suppressions, and pacing rules. | | `sending?` | `scope` | - | Reads, plus sending: send an email, reply or forward a thread, edit and send drafts, reschedule, and cancel. Cannot change configuration. | | `read?` | `scope` | - | Reads only: list and retrieve emails, threads, domains, mailboxes, deliveries, suppressions, and pacing state. | Concretely: | Operation | `read` | `sending` | `full` | | --------------------------------------------------------------------------------------------------------- | :----: | :-------: | :----: | | List and retrieve emails, threads, attachments | ✓ | ✓ | ✓ | | Read domains, mailboxes, webhook endpoints and deliveries, suppressions, pacing | ✓ | ✓ | ✓ | | [Send an email](/guides/sending), [reply on a thread](/guides/threads#replying) | | ✓ | ✓ | | [Reschedule](/guides/scheduling#rescheduling) or [cancel](/guides/scheduling#canceling) a scheduled email | | ✓ | ✓ | | [Edit, send or discard a draft](/guides/drafts#editing-and-sending-from-code) | | ✓ | ✓ | | Create, update, delete domains, mailboxes, OAuth apps, webhook endpoints | | | ✓ | | Manage [suppressions](/guides/suppressions) and [pacing rules](/guides/pacing) | | | ✓ | | Create and delete API keys | | | ✓ | :::tip A worker that only sends should hold a `sending` key, and an analytics job that only reads should hold a `read` one. Both are ordinary keys — the narrowing is enforced server-side, so a leaked `read` key cannot send. ::: ## Managing keys Keys are created in the [console](https://aiinbx.com/app) or through the API with a `full` key. The plaintext key is returned **once**, on the create call: ```ts TypeScript const created = await aiinbx.apiKeys.create({ name: "background worker", scope: "sending", }) console.log(created.key) // the only time you see it ``` ```python Python created = client.api_keys.create(name="background worker", scope="sending") print(created["key"]) # the only time you see it ``` ```bash curl curl https://api.aiinbx.com/api/v2/api-keys \ -H "Authorization: Bearer $AI_INBX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "background worker", "scope": "sending" }' ``` Afterwards a key lists as metadata only — its `prefix`, `scope`, `created_at`, and `last_used_at`. `last_used_at` is the field to check before deleting a key you're no longer sure about. ### Rotating Rotate a key by creating a replacement, deploying it, and deleting the old key after the cutover. 1. **Create the replacement** Same scope, a name that says what it replaces. 2. **Deploy it** Roll it out everywhere the old key was configured. 3. **Watch last_used_at** List keys until the old one stops advancing. 4. **Delete the old key** `apiKeys.delete(id)` — takes effect immediately. Deletion is permanent. The key disappears from the list and authenticates nothing. ## Request IDs Every response carries `X-Request-ID`, and every error body repeats it as `request_id`. If you send your own `X-Request-ID` — up to 128 characters of `A-Za-z0-9._:-` — it's echoed back instead of a generated one, which is what you want when you already have a trace ID to correlate against. See [Conventions](/reference/conventions#request-ids). --- # CLI Source: https://docs.aiinbx.com/cli `aiinbx` runs your AI Inbx workspace from a terminal, a script or an agent. Every API operation is a command. A few jobs only a local tool can do have commands of their own: sending files and React Email templates, forwarding webhook events to `localhost`, blocking until an email arrives, and checking a domain's DNS. ```sh aiinbx login aiinbx send --from you@yourdomain.com --to someone@example.com \ --subject "Hello" --text "Sent from the terminal" ``` ## Install The CLI is a single executable. Nothing else, not Node and not Bun, has to be installed to run it. {/* Generated by scripts/cli-install.ts from the shared API contract. */} ```sh macOS & Linux curl -fsSL https://aiinbx.com/install.sh | sh ``` ```sh Homebrew brew install aiinbx/tap/aiinbx ``` ```sh npm npm install -g @aiinbx/cli ``` ```powershell Windows powershell -c "irm https://aiinbx.com/install.ps1 | iex" ``` To run it once without installing: `npx @aiinbx/cli --help`. The CLI looks for a newer release once a day and, while one is out, says so after each command at a terminal. `aiinbx update` installs it the way the CLI was installed: through npm, pnpm, Bun, Yarn or Homebrew, or, for the install script's copy, by downloading the release, checking it against its checksums and replacing itself. `aiinbx uninstall` removes the CLI the same way, along with the PATH entry the install script added. It signs out of every profile and deletes the config directory; `--keep-config` keeps them. ## Sign in ```sh aiinbx login # opens the browser aiinbx login --device # a code to approve on another device (SSH, containers) echo "$AI_INBX_API_KEY" | aiinbx login --with-api-key aiinbx whoami ``` A login acts for your account in the workspaces you grant it. When it reaches more than one, pick the one commands act in with `aiinbx workspace use `, or pass `--workspace` for a single command. An [API key](/authentication) belongs to one workspace and needs neither. The consent page can instead make the login an inbox: one or more addresses it sends from and reads, for an agent. `aiinbx whoami` then says `"mode": "inbox"` with its addresses, help lists only the commands an inbox may run, and `send` goes from the inbox without `--from`. See [Give your agent an inbox](/guides/agent-inbox). Credentials are taken from `--api-key` first, then `AI_INBX_API_KEY`, then the signed-in profile. A profile's secret is kept in the macOS Keychain, the Secret Service on Linux, or DPAPI on Windows. `-p ` or `AI_INBX_PROFILE` picks a profile, and `aiinbx auth switch ` makes one the default. ## Commands Every API operation is a command, `aiinbx `. Path parameters are arguments and fields are flags. A resource on its own lists it: ```sh aiinbx threads --limit 5 aiinbx threads retrieve thr_123 aiinbx threads reply thr_123 --text "Thanks, on it" aiinbx domains create --name yourdomain.com --region eu-central-1 aiinbx events list --type email.bounced --type email.complained --limit 50 aiinbx webhook-endpoints create --url https://example.com/hooks --subscriptions email.received aiinbx attachments download att_123 --output invoice.pdf ``` - Repeatable flags take one value each: `--to a@x.com --to b@x.com`. - Booleans are switches: `--track-opens`, `--no-track-opens`. - Nested fields take JSON: `--tracking '{"opens":false}'`. - `--data` takes the whole body as JSON, `@file.json`, or `-` for stdin. Flags are laid over it. - `'[]'` sends an empty list: `aiinbx emails update eml_123 --cc '[]'` clears it. - Lists take `--limit` and `--cursor`. `--all` fetches every page. - Commands that cannot be undone ask first, or need `--yes` without a terminal. The commands are generated from the same contract as the [API reference](/api) and the SDKs, so they cannot drift from the API. `aiinbx --help` shows every flag with examples. ## Send ```sh aiinbx send --from you@yourdomain.com --to a@example.com --subject Report \ --html-file report.html --text-file report.txt --attach report.pdf cat notes.md | aiinbx send --from you@yourdomain.com --to a@example.com \ --subject Notes --text-file - aiinbx send --from you@yourdomain.com --to a@example.com --subject Welcome \ --react emails/welcome.tsx --props '{"name":"Ada"}' \ --scheduled-at 2026-10-01T09:00:00Z ``` ```text Idempotency key 4e306697-7390-43c4-8e61-cb5a455ff376 ✓ Sent eml_5c2e… to a@example.com (queued) ``` `--react` renders a [React Email](/integrations/react-email) component with the `react` and `@react-email/render` installed in the template's own project, or the CLI's own copy where the project has none. Every send carries an [idempotency key](/reference/conventions), `--idempotency-key` or a generated one, so a retried send never goes out twice. ### Drafts and scheduled sends `--draft` stores the email instead of sending it, and `--scheduled-at` holds it until then. Both work on `send`, `threads reply` and `threads forward`: ```sh aiinbx threads reply thr_123 --text "Draft for Ada to check" --draft # ✓ Drafted eml_9d4a… to ada@example.com — review it at https://aiinbx.com/… aiinbx emails update eml_9d4a… --text "Checked and fixed" aiinbx emails send-draft eml_9d4a… # or --scheduled-at to send it later aiinbx emails cancel eml_7b1c… # a scheduled email that has not gone out ``` See [Drafts](/guides/drafts) and [Scheduling](/guides/scheduling). ## Listen: webhooks on localhost ```sh aiinbx listen --forward-to localhost:3000/api/webhooks ``` ```text Ready. Forwarding every event to http://localhost:3000/api/webhooks Signing secret whsec_jeMeEt8G… (aiinbx listen --print-secret) Ctrl-C to stop. 18:54:11 email.received evt_a1b2c3… → 200 7 ms 18:54:12 email.delivered evt_b2c3d4… → 200 1 ms 18:54:40 email.bounced evt_c3d4e5… → 500 3 ms ``` `listen` forwards your workspace's events to a URL on your machine. Each one arrives as a real [webhook delivery](/webhooks) would: the same JSON body, the same `AIInbx-Event-Id` and `AIInbx-Signature` headers, the same [signature scheme](/webhooks/verifying). There is no tunnel to run and no endpoint to register. The CLI follows the [events API](/api) live and posts each event the moment it is recorded. The deliveries are signed with a secret of your profile's own. It stays the same from run to run, so put it in your app's environment once: ```sh aiinbx listen --print-secret # whsec_… AI_INBX_WEBHOOK_SECRET=$(aiinbx listen --print-secret) npm run dev ``` Your handler's `verifyWebhookRequest(request, process.env.AI_INBX_WEBHOOK_SECRET)` then accepts local deliveries unchanged. In production the same code gets the endpoint's secret. ```sh aiinbx listen --forward-to localhost:3000/api/webhooks \ --events email.received,email.bounced \ --since 1h ``` - `--events` forwards only these types. - `--since` replays from an ISO 8601 time or a duration ago (`15m`, `2h`) before it goes on listening. Without it, `listen` starts with what happens next. - At a terminal it prints a line per event: its time, type and id, what your server answered, and how long it took. Anywhere else it prints one JSON object per line: `{"event_id","type","created_at","status","latency_ms","error"}`. - A server that is down or answers an error is logged, and the next event still goes out. `listen` is not retried like a real endpoint. :::note[The summary body] Deliveries carry the body every endpoint receives. The `data.email` that an endpoint with `payload: "full"` is also sent is not included. Read the email by `data.email_id`. ::: ## Wait: block until an email arrives ```sh aiinbx wait --to qa@yourdomain.com --subject "verification code" --timeout 1m ``` ```text id eml_8c1e4f… thread_id thr_3f9a2c… from Acme to qa@yourdomain.com subject Your verification code created_at 2026-09-26T16:54:11.706Z text Your code is 482913. ``` `wait` blocks until a matching email arrives, prints it and exits `0`. When `--timeout` passes first (two minutes by default), it exits `124`, as `timeout` does. If the API never answered at all, it exits `1` with the API's error: an outage, not a missing email. It is made for agents and end-to-end tests: sign up, wait for the verification email, read the code. | Flag | Matches | | ------------------------- | --------------------------------------------------------- | | `--from ` | Part of the sender: an address, a domain or a name | | `--to ` | Part of a recipient, in `to` or `cc` | | `--subject ` | Part of the subject | | `--thread ` | Only this thread | | `--direction ` | `inbound` (the default) or `outbound` | | `--since