[
  {
    "slug": "api-key-scopes",
    "title": "API key permissions",
    "description": "Choose and change precisely what each application, CLI or agent can do.",
    "group": "Guides",
    "sections": [
      {
        "title": "Choosing access",
        "text": "Open Settings > API keys. Create a key, give it a meaningful name and select individual permissions. One key can combine multiple scopes. Read and write permissions are independent: granting write does not grant read. Start with the permissions your integration actually needs."
      },
      {
        "title": "Common combinations",
        "text": "Use these combinations as starting points, then narrow them to your workflow.",
        "rows": [
          [
            "Workflow",
            "Scopes"
          ],
          [
            "Send transactional email",
            "emails:send"
          ],
          [
            "Send and monitor delivery or engagement",
            "emails:send, emails:read"
          ],
          [
            "Read received email",
            "inboxes:read, messages:read"
          ],
          [
            "Create and inspect test inboxes",
            "inboxes:create, inboxes:read, messages:read"
          ],
          [
            "Manage sending domains",
            "domains:read, domains:write"
          ]
        ]
      },
      {
        "title": "Inboxes",
        "text": "Select only the operations this integration needs.",
        "rows": [
          [
            "Scope",
            "What it allows"
          ],
          [
            "inboxes:read",
            "List shared application inboxes and their addresses. Does not reveal message bodies."
          ],
          [
            "inboxes:create",
            "Create application and test inboxes. Add View inboxes to list them and Read messages to inspect received email."
          ],
          [
            "messages:read",
            "Read shared inbox message bodies and attachments. Private business inboxes remain session-only."
          ]
        ]
      },
      {
        "title": "Email",
        "text": "Select only the operations this integration needs.",
        "rows": [
          [
            "Scope",
            "What it allows"
          ],
          [
            "emails:send",
            "Send email using an allowed sender. Sending quotas, verification and suppression rules still apply. Does not include reading email."
          ],
          [
            "emails:read",
            "View sent email records, delivery status, usage and engagement analytics. Sent records may include message content. Also permits listing domains for compatibility."
          ]
        ]
      },
      {
        "title": "Designs",
        "text": "Select only the operations this integration needs.",
        "rows": [
          [
            "Scope",
            "What it allows"
          ],
          [
            "designs:read",
            "Read reusable HTML email designs and brand settings."
          ],
          [
            "designs:write",
            "Create, edit and delete designs, upload brand assets and request AI designs. Add View email designs to browse them."
          ]
        ]
      },
      {
        "title": "Domains",
        "text": "Select only the operations this integration needs.",
        "rows": [
          [
            "Scope",
            "What it allows"
          ],
          [
            "domains:read",
            "Read domain verification status and the DNS records needed for setup."
          ],
          [
            "domains:write",
            "Add, verify and remove sending domains. This does not change records at your DNS provider."
          ]
        ]
      },
      {
        "title": "Webhooks",
        "text": "Select only the operations this integration needs.",
        "rows": [
          [
            "Scope",
            "What it allows"
          ],
          [
            "webhooks:read",
            "List workspace webhook endpoints and configuration."
          ],
          [
            "webhooks:write",
            "Create, update or disable webhook endpoints that receive workspace events."
          ]
        ]
      },
      {
        "title": "Suppression",
        "text": "Select only the operations this integration needs.",
        "rows": [
          [
            "Scope",
            "What it allows"
          ],
          [
            "suppressions:read",
            "Check recipients blocked from outreach in this workspace."
          ],
          [
            "suppressions:write",
            "Block recipients from outreach in this workspace. Does not remove account-wide opt-outs."
          ]
        ]
      },
      {
        "title": "Editing an existing key",
        "text": "An owner or admin can choose Edit permissions, add or remove scopes and save. The secret and expiration stay the same. New requests use the updated permissions; requests already running may finish. An expired or revoked key cannot be edited. Revoking a key removes all access."
      },
      {
        "title": "Update endpoint",
        "text": "PATCH /api/v2/keys/{id} requires an owner/admin user session and the selected workspace. Send a name and the complete, nonempty scopes array. This replaces the permissions, rather than appending them. Unknown scopes are rejected. The response contains metadata only, never a new secret.",
        "code": "{\n  \"name\": \"Production delivery\",\n  \"scopes\": [\n    \"emails:send\",\n    \"emails:read\"\n  ]\n}"
      },
      {
        "title": "Credential boundaries",
        "text": "Workspace keys work with HTTP, the CLI and agents, but cannot administer keys, members or billing or access private business inboxes. SMTP credentials and webhook signing secrets are different credentials. Anonymous testing uses a temporary inbox token, not a workspace key. Store all secrets server-side, never in browser code."
      },
      {
        "title": "Expiry and restrictions",
        "text": "Keys created in the dashboard expire after 30 days. The create API supports 1-365 days. Scopes do not bypass workspace boundaries, domain verification, quotas, suppression rules or sending safeguards. A missing scope produces 403. Invalid, expired or revoked credentials are rejected."
      }
    ]
  },
  {
    "slug": "",
    "title": "Build email into your product.",
    "description": "Your domain. Your branding. One connected email workflow.",
    "group": "Guides",
    "sections": [
      {
        "title": "Start here",
        "text": "Create and confirm an account, select a workspace, verify your domain, and create a scoped API key. Every plan includes unlimited inboxes. Start with Quickstart, then use the endpoint reference for exact fields."
      },
      {
        "title": "Choose your integration",
        "text": "REST API: submit email and read messages from your server. CLI: administer workspaces, domains and teams. SMTP: connect existing applications. Webhooks: receive signed delivery, bounce and incoming events."
      },
      {
        "title": "Current availability",
        "text": "Create an account, confirm your email and start sending with your free allowance. No manual approval is required. Queue acceptance is not final delivery. Batch sends, scheduling, attachment sending, open tracking and click tracking are not supported in this release."
      },
      {
        "title": "Examples and environments",
        "text": "Examples use https://inboxit.wtf/api/v2 and fictional identifiers. Replace domains with your own and recipient placeholders with your recipients. Keep credentials on your server."
      }
    ]
  },
  {
    "slug": "quickstart",
    "title": "Quickstart",
    "description": "From a free account to a delivery and reply.",
    "group": "Guides",
    "sections": [
      {
        "title": "1. Authenticate",
        "text": "Create an account and confirm your email. Pair the CLI with your signed-in browser, then select a workspace.",
        "code": "npm install -g @onedigitsa/inboxit\ninboxit login\ninboxit workspaces list\ninboxit workspace use --id WORKSPACE_UUID"
      },
      {
        "title": "2. Verify your domain",
        "text": "Publish the returned ownership and DKIM TXT records at your DNS provider. Values are unique to your domain.",
        "code": "inboxit domains add --name mail.yourbrand.com\ninboxit domains verify --id DOMAIN_UUID"
      },
      {
        "title": "3. Create a receiving inbox",
        "text": "Wait for status active. Add an MX record for your dedicated subdomain pointing exclusively to mail.inboxit.wtf, priority 10, before assigning the custom address. Preserve unrelated root-domain mail records.",
        "code": "inboxit inboxes create --name Support --idempotency-key support-001\ninboxit inboxes list\ninboxit inboxes address --id INBOX_UUID --address hello@mail.yourbrand.com"
      },
      {
        "title": "4. Send and observe",
        "text": "Use your recipient’s email address. New sends return a pending status. Check Logs or subscribe to webhooks to track delivery. Reuse an idempotency key only for the same logical message.",
        "code": "inboxit emails send --from hello@mail.yourbrand.com --to recipient@example.com --subject Hello --text \"Reply to this email.\" --idempotency-key welcome-001\ninboxit logs list"
      },
      {
        "title": "5. Read the reply",
        "text": "Reply from the recipient mailbox. Use the mailbox UID returned by the list call to fetch the message. Register email.received to automate this step.",
        "code": "inboxit messages list --id INBOX_UUID\ninboxit messages get --id INBOX_UUID --message MESSAGE_UID"
      }
    ]
  },
  {
    "slug": "testing",
    "title": "Test email workflows",
    "description": "Temporary inboxes, bounded waits, and code/link extraction through the dashboard, API and CLI.",
    "group": "Guides",
    "sections": [
      {
        "title": "Open Testing",
        "text": "Open Testing in your workspace dashboard. Native temporary addresses receive internet email once their status is active. This update is available in the local website and source CLI; the npm package has not been republished."
      },
      {
        "title": "Prepare before sending",
        "text": "Create a temporary inbox (60–86400 seconds, default one hour). Start a wait BEFORE triggering your application. Only messages arriving after that boundary can match. Sender matches an exact email address; subject matches a case-insensitive substring. Waits last 1–300 seconds. Wait until the address is active, then send from your application or an external email account."
      },
      {
        "title": "CLI workflow",
        "text": "Use the CLI from this checkout. Create a workspace API key with inboxes:create, inboxes:read and messages:read scopes and set INBOXIT_TOKEN. Start the wait in one terminal, then trigger your application in another. A timeout returns JSON and exit code 2.",
        "code": "node cli/bin/inboxit.mjs testing create --name Signup --ttl_seconds 3600 --idempotency-key signup-001 --origin http://127.0.0.1:8790\nnode cli/bin/inboxit.mjs testing wait --id INBOX_UUID --subject Verify --timeout_seconds 60 --origin http://127.0.0.1:8790"
      },
      {
        "title": "API routes",
        "text": "All routes require workspace-scoped bearer authentication. Creation also requires Idempotency-Key. POST wait returns a run immediately; poll GET run until matched, timed_out or cancelled.",
        "rows": [
          [
            "Method",
            "Path below /api/v2",
            "Body / behavior"
          ],
          [
            "GET",
            "/testing/inboxes",
            "List active temporary inboxes"
          ],
          [
            "POST",
            "/testing/inboxes",
            "name, ttl_seconds; returns inbox with address and test_expires_at"
          ],
          [
            "DELETE",
            "/testing/inboxes/{id}",
            "Delete contents and disable address"
          ],
          [
            "POST",
            "/testing/inboxes/{id}/wait",
            "sender, subject, timeout_seconds; returns run id"
          ],
          [
            "GET",
            "/testing/runs/{id}",
            "Status, matched message and extraction"
          ],
          [
            "DELETE",
            "/testing/runs/{id}",
            "Cancel a waiting run"
          ],
          [
            "GET",
            "/testing/inboxes/{id}/messages/{message}/extract",
            "Extract from an existing message"
          ]
        ]
      },
      {
        "title": "Extraction and expiry",
        "text": "Extraction returns codes (4–8 digit candidates), links (HTTP/HTTPS candidates), and singular code/link only when exactly one candidate exists. Multiple candidates are flagged ambiguous. Content is untrusted: links are never followed automatically. Expiry disables reception and removes stored messages and runs. Missing resources return 404; expired inbox access returns 410 before cleanup. Native expiry rejects new mail and retries mailbox cleanup and replaces delivery routes with rejection markers independently of the local website. Incoming mail uses your account allowance."
      }
    ]
  },
  {
    "slug": "authentication",
    "title": "Authentication",
    "description": "Scoped keys for application traffic. User sessions for administration.",
    "group": "Guides",
    "sections": [
      {
        "title": "Create a key",
        "text": "Keys are workspace-bound, shown once, and expire after 1–365 days (default 30). An account can have ten active keys. Save tokens in your secret manager.",
        "code": "inboxit keys create --name backend --scopes emails:send,emails:read,inboxes:read,messages:read"
      },
      {
        "title": "Scopes",
        "text": "Grant the smallest set your integration needs.",
        "rows": [
          [
            "Scope",
            "Permission"
          ],
          [
            "inboxes:read",
            "List inboxes"
          ],
          [
            "inboxes:create",
            "Provision an inbox"
          ],
          [
            "messages:read",
            "Read messages and raw source"
          ],
          [
            "emails:send",
            "Submit API or SMTP email"
          ],
          [
            "emails:read",
            "Read outgoing emails, domains, analytics, logs and usage"
          ]
        ]
      },
      {
        "title": "HTTP authentication",
        "text": "Send Authorization: Bearer <key>. X-Workspace-Id selects a workspace for user sessions; a key cannot cross its workspace boundary.",
        "code": "curl https://inboxit.wtf/api/v2/usage -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "Management permissions",
        "text": "Domain mutations, receiving-address changes, key creation, teams and webhook management require an owner/admin user session. Use inboxit login. An emails:send key cannot administer resources. Cookie-authenticated browser writes also require X-CSRF-Token; the CLI handles this."
      },
      {
        "title": "Session lifecycle",
        "text": "CLI pairing requires explicit browser approval and expires after ten minutes. CLI logout revokes that credential. Parent-session logout invalidates delegated access. Do not share credentials with an agent beyond the account and permissions it needs."
      }
    ]
  },
  {
    "slug": "cli",
    "title": "CLI & agent skill",
    "description": "The published InboxIt terminal client.",
    "group": "Guides",
    "sections": [
      {
        "title": "Install and sign in",
        "text": "The package is @onedigitsa/inboxit; the command is inboxit. Email login prompts for a hidden password. Sign-up requires confirmation.",
        "code": "npm install -g @onedigitsa/inboxit\ninboxit login\ninboxit whoami\ninboxit help\ninboxit commands"
      },
      {
        "title": "Workspace and account",
        "text": "Workspace names are 1–10 characters. Select by returned UUID.",
        "code": "inboxit signup --email you@example.com --name \"Your Name\"\ninboxit login --email you@example.com\ninboxit workspaces create --name prod\ninboxit workspace use --id WORKSPACE_UUID"
      },
      {
        "title": "Agent skill",
        "text": "Download the bundled instructions and give the file to your agent. Its permissions remain those of the credential you grant.",
        "code": "inboxit skill --output ./inboxit-skill.md"
      },
      {
        "title": "Structured automation",
        "text": "JSON goes to stdout; errors go to stderr with a nonzero exit. --data accepts JSON, @file.json or - for stdin. --query accepts a JSON object. --output creates a file without overwriting. Writes are not automatically retried.",
        "code": "inboxit emails send --data @email.json --idempotency-key order-001\ninboxit logs list --query '{\"status\":\"failed\",\"limit\":20}'\ninboxit messages raw --id INBOX_UUID --message 42 --output message.eml"
      },
      {
        "title": "Configuration",
        "text": "--workspace overrides the selected workspace. --origin or INBOXIT_ORIGIN overrides the HTTPS origin. INBOXIT_TOKEN supplies a scoped API key. Login credentials are stored per origin in ~/.inboxit/credentials.json; INBOXIT_CONFIG_DIR overrides this directory. Keep it private."
      },
      {
        "title": "Coverage",
        "text": "Endpoint pages include matching commands. billing get maps to /usage. smtp create-key maps to key creation. request can call implemented routes; it does not add unsupported features. Whole-account/workspace deletion is not implemented.",
        "code": "inboxit request GET /usage\ninboxit logout"
      }
    ]
  },
  {
    "slug": "domains",
    "title": "Domains & DNS",
    "description": "Authenticate your sender and receive on your own domain.",
    "group": "Guides",
    "sections": [
      {
        "title": "Add a domain",
        "text": "Use a domain or subdomain without a scheme, path or email address. The returned records array has purpose, type, host, value and required. Pending domains count toward account limits.",
        "code": "inboxit domains add --name mail.yourbrand.com\ninboxit domains provider --id DOMAIN_UUID"
      },
      {
        "title": "Publish and verify",
        "text": "Ownership and DKIM TXT records are required; DMARC is recommended. Hosts are fully qualified: providers that append the zone may need a relative host. Preserve existing mail records. Verification returns status, checks and checked_at. Wait at least ten seconds between checks.",
        "code": "inboxit domains verify --id DOMAIN_UUID"
      },
      {
        "title": "Receiving DNS",
        "text": "For a dedicated receiving subdomain, set MX to mail.inboxit.wtf with priority 10. Assignment requires MX records to point exclusively to that host. Do not replace root-domain MX used by another provider. A verified sending domain alone does not create a receiving inbox."
      },
      {
        "title": "Remove safely",
        "text": "Remove custom receiving routes before deleting a domain. A domain with attached addresses returns 409. Address removal does not delete the inbox or messages.",
        "code": "inboxit inboxes remove-address --id INBOX_UUID\ninboxit domains delete --id DOMAIN_UUID"
      }
    ]
  },
  {
    "slug": "sending",
    "title": "Send branded email",
    "description": "Text and HTML from a verified sender.",
    "group": "Guides",
    "sections": [
      {
        "title": "Sender and branding",
        "text": "Use an active platform inbox address or a verified domain in the selected workspace. from is a bare address; from_name supplies its display name. text is required even with html. HTML is your branding, without an InboxIt marketing footer."
      },
      {
        "title": "Delivery lifecycle",
        "text": "201 means accepted. pending means awaiting processing, queued means handed to delivery, delivered means remote server acceptance. It does not guarantee inbox placement. Native provider failures may appear as failed while emitting email.bounced."
      },
      {
        "title": "Idempotency",
        "text": "Idempotency-Key is required: 1–100 letters, digits, underscores or hyphens. Reuse the same key and payload after an ambiguous timeout. A different payload with the same key returns 409. If the delivery status is uncertain, check the logs before sending again."
      },
      {
        "title": "Outreach and unsubscribe",
        "text": "Set purpose to outreach for paced API delivery with unsubscribe controls. By default InboxIt adds a workspace unsubscribe footer and one-click headers. Use unsubscribe_url for your HTTPS preference page on an exact hostname verified in this workspace. The one-click header still uses InboxIt unless you also supply unsubscribe_one_click_url. A custom one-click endpoint must accept unauthenticated form POSTs with List-Unsubscribe=One-Click. Your backend must immediately call POST /workspace-suppressions with the recipient and reason unsubscribe, and stop your own follow-ups. Do not unsubscribe on GET: link scanners visit links. Use opaque recipient tokens, not exposed email addresses."
      },
      {
        "title": "Integration controls",
        "text": "Use a separate workspace and scoped API key per customer. Domain, webhook and workspace-suppression APIs support explicitly granted scopes. POST /suppressions remains session-admin only and account-wide. GET /emails/:id reports status and next_attempt; POST /emails/:id/cancel cancels pending jobs only. Your campaign engine owns sequences, schedules, sender rotation and stop-on-reply. API outreach defaults to 50 sends per domain across the account in 24 hours, with 120 seconds between dispatches and a 24-hour queue expiry. Unlimited Enterprise volume does not remove these safeguards."
      },
      {
        "title": "Content limits",
        "text": "One recipient. Subject up to 200 characters; text up to 10,000; HTML up to 80,000; display name up to 100. Up to five attachments, 2 MB each and 5 MB total. No CC/BCC, scheduled or batch sends. Quotas, suppressions and account verification apply."
      }
    ]
  },
  {
    "slug": "receiving",
    "title": "Receive email",
    "description": "Provision inboxes and fetch incoming messages.",
    "group": "Guides",
    "sections": [
      {
        "title": "Provisioning",
        "text": "POST /inboxes returns 202. Poll the list until active. All plans have unlimited inboxes; volume, storage and retention still apply."
      },
      {
        "title": "Custom addresses",
        "text": "POST /inboxes/{id}/receiving-address assigns or renames an address. Verify its domain and MX first. A routing 503 can mean a pending durable change; inspect receiving_status before retrying. DELETE removes the custom route."
      },
      {
        "title": "Pagination and IDs",
        "text": "List responses contain uid_validity, messages and next_before. Pass next_before as before; limit defaults to 20, maximum 50. IDs here are mailbox UIDs, not outbound UUIDs. Persist inbox ID, UID validity and UID together."
      },
      {
        "title": "Events and raw messages",
        "text": "email.received contains message identifiers, not the body. Fetch details separately. /messages/{uid}/raw downloads an application/octet-stream .eml. New webhook endpoints do not replay historical incoming mail. Read messages before retention expires."
      }
    ]
  },
  {
    "slug": "threads",
    "title": "Replies & threads",
    "description": "Connect responses to their original messages.",
    "group": "Guides",
    "sections": [
      {
        "title": "Store Message-ID",
        "text": "Store message_id from the send response alongside your conversation ID. This RFC Message-ID differs from the outbound UUID."
      },
      {
        "title": "Route replies",
        "text": "Send from your assigned custom receiving address, or set reply_to to it. Domain verification enables sending; an active receiving route and MX enable receiving."
      },
      {
        "title": "Reply with context",
        "text": "Set in_reply_to to the incoming message’s Message-ID, including angle brackets. Read In-Reply-To and References from message headers/raw source to map conversations. There is no separate threads endpoint. Subject matching alone is unreliable.",
        "code": "inboxit emails send --data @reply.json --idempotency-key reply-001\n\n// reply.json\n{\"from\":\"hello@mail.yourbrand.com\",\"to\":\"recipient@example.com\",\"subject\":\"Re: Hello\",\"text\":\"Thanks!\",\"in_reply_to\":\"<original@example.com>\"}"
      }
    ]
  },
  {
    "slug": "webhooks",
    "title": "Webhooks & signatures",
    "description": "Signed delivery, bounce and incoming events.",
    "group": "Guides",
    "sections": [
      {
        "title": "Register",
        "text": "An owner/admin can register five active endpoints per workspace. Public HTTPS port 443 is required; private destinations and redirects are blocked. Store the returned secret immediately.",
        "code": "inboxit webhooks create --url https://yourbrand.com/hooks/inboxit --events email.delivered,email.bounced,email.received"
      },
      {
        "title": "Payloads",
        "text": "Envelope: id, type, created_at, workspace_id, data. Native delivery/bounce data: email_id, message_id, from, to, provider_status. Incoming data: inbox_id, uid, uid_validity, address, message_id. Fetch message bodies separately.",
        "code": "{\"id\":\"EVENT_UUID\",\"type\":\"email.received\",\"created_at\":\"2026-10-23T12:00:00Z\",\"workspace_id\":\"WORKSPACE_UUID\",\"data\":{\"inbox_id\":\"INBOX_UUID\",\"uid\":\"42\",\"uid_validity\":\"123456\",\"address\":\"hello@mail.yourbrand.com\",\"message_id\":\"<reply@example.com>\"}}"
      },
      {
        "title": "Verify signatures",
        "text": "Use the unmodified raw request Buffer before parsing JSON. Headers: webhook-id, webhook-timestamp, webhook-signature. Sign id.timestamp.rawBody with HMAC-SHA256 using the secret as a UTF-8 string. Enforce a five-minute window, then persist/deduplicate event IDs.",
        "code": "import {createHmac, timingSafeEqual} from 'node:crypto';\n\n\n\nexport function verify(rawBody, headers, secret) {\n\n\n\n  const id = headers['webhook-id'];\n\n\n\n  const time = headers['webhook-timestamp'];\n\n\n\n  const signature = headers['webhook-signature'];\n\n\n\n  if (!id || !/^\\d+$/.test(time || '') || !signature) return false;\n\n\n\n  if (Math.abs(Date.now() / 1000 - Number(time)) > 300) return false;\n\n\n\n  const hex = createHmac('sha256', secret)\n\n\n\n    .update(id + '.' + time + '.').update(rawBody).digest('hex');\n\n\n\n  const expected = Buffer.from('v1=' + hex);\n\n\n\n  const actual = Buffer.from(signature);\n\n\n\n  return actual.length === expected.length && timingSafeEqual(actual, expected);\n\n\n\n}\n\n\n\n// After verification: persist/deduplicate event.id, enqueue work, return 2xx."
      },
      {
        "title": "Retries",
        "text": "At-least-once delivery: non-2xx/network failures retry up to eight total attempts, exponential delays from 30 seconds capped at one hour. IDs stay stable; ordering is not guaranteed. Acknowledge only after durable acceptance. GET /webhooks includes the latest 100 delivery records.",
        "code": "inboxit webhooks list\ninboxit webhooks retry --id DELIVERY_UUID"
      },
      {
        "title": "Disable and rotate",
        "text": "DELETE disables an endpoint and cancels queued deliveries; an in-flight request may arrive. No update/rotation endpoint exists. Create a replacement, configure its secret, then disable the old endpoint. Deduplicate during overlap."
      }
    ]
  },
  {
    "slug": "logs",
    "title": "Delivery logs",
    "description": "Filter and paginate workspace activity.",
    "group": "Guides",
    "sections": [
      {
        "title": "Query logs",
        "text": "status: all, pending, queued, delivered, bounced, failed, uncertain, received. limit defaults to 50, maximum 100. Pass next unchanged as before; null ends pagination.",
        "code": "inboxit logs list --query '{\"status\":\"failed\",\"limit\":25}'"
      },
      {
        "title": "Fields",
        "text": "items contain id, email_id, status, recipient, subject, created_at, delivered_at, failure_code and attempts. Incoming email_id/subject may be null. No message bodies. Results are newest first by timestamp and ID."
      },
      {
        "title": "Investigate",
        "text": "Correlate email_id with outgoing records/webhooks. Check sender DNS, suppression, plan usage and recipient address and suppression status. Do not resend uncertain deliveries with a new key blindly. Webhook transport failures are separate records in GET /webhooks."
      }
    ]
  },
  {
    "slug": "analytics",
    "title": "Analytics",
    "description": "UTC workspace activity and delivery outcomes.",
    "group": "Guides",
    "sections": [
      {
        "title": "Time series",
        "text": "GET /analytics?days=30 accepts 7, 30 or 90 days. Returns days, timezone, series and totals. Series items contain day, sent, delivered, bounced, failed and received.",
        "code": "inboxit analytics get --days 30"
      },
      {
        "title": "Definitions",
        "text": "Outbound counts use creation day and current status, so historical totals can change as delivery completes. sent counts submitted rows. Incoming counts use recorded incoming usage. Native hard failures can count as failed rather than bounced."
      },
      {
        "title": "Scope",
        "text": "Analytics is workspace-scoped. GET /usage is account-wide. Opt-in HTML sends expose opened/clicked unique email counts, opens/clicks event totals, and per-link counts. Use tracking: {opens: true, clicks: true} when sending, or CLI --track-opens --track-clicks with --data @email.json. Image blocking can hide opens and privacy proxies/link scanners can inflate events. Direct SMTP tracking and engagement webhooks are not included. delivered means remote mail-server acceptance."
      }
    ]
  },
  {
    "slug": "usage",
    "title": "Usage & limits",
    "description": "Unlimited inboxes with account-wide allowances.",
    "group": "Guides",
    "sections": [
      {
        "title": "Read usage",
        "text": "Fields: plan, name, domain_limit, daily_limit, monthly_limit, incoming_limit, storage_limit, retention_days, inbox_limit, price, daily_used, monthly_used, incoming_used, sending_paused, pause_reason and mode. null inbox_limit means unlimited; null daily_limit means no daily cap.",
        "code": "inboxit usage get"
      },
      {
        "title": "Counters",
        "text": "Outgoing counters count submitted rows, including unsuccessful messages, in the current UTC day/month. Incoming has a separate monthly allowance. All owner workspaces share quotas. Pending domains count. Usage does not report current storage bytes."
      },
      {
        "title": "Plan allowances",
        "text": "Monthly outgoing and incoming allowances are separate and equal.",
        "rows": [
          [
            "Plan",
            "Monthly volume / price",
            "Domains",
            "Storage / retention"
          ],
          [
            "Free",
            "1,000 each / $0; 100 outgoing/day",
            "1",
            "100 MiB / 7 days"
          ],
          [
            "Build",
            "50,000 / $12; 75,000 / $22",
            "5",
            "1 GiB / 30 days"
          ],
          [
            "Scale",
            "100,000 / $39; 250,000 / $79; 500,000 / $149; 1,000,000 / $279",
            "25",
            "5 GiB / 30 days"
          ]
        ]
      },
      {
        "title": "Abuse controls",
        "text": "Unlimited inboxes does not remove volume, storage or retention limits. Suppressed recipients cannot be sent to. Complaints or excessive bounces can pause sending. Inspect pause_reason and contact support; a new key does not bypass a pause."
      }
    ]
  },
  {
    "slug": "smtp",
    "title": "SMTP integration",
    "description": "Connect existing applications, including Supabase.",
    "group": "Guides",
    "sections": [
      {
        "title": "Connection",
        "text": "Require STARTTLS and certificate verification. Password is a workspace API key with emails:send.",
        "rows": [
          [
            "Setting",
            "Value"
          ],
          [
            "Host",
            "mail.inboxit.wtf"
          ],
          [
            "Port",
            "587"
          ],
          [
            "TLS",
            "STARTTLS required (not implicit TLS)"
          ],
          [
            "Username",
            "inboxit"
          ],
          [
            "Password",
            "Sending API key"
          ]
        ]
      },
      {
        "title": "Credentials",
        "text": "Use a dedicated expiring key for each integration. Revoking it disables SMTP access.",
        "code": "inboxit smtp create-key --name supabase --scopes emails:send\ninboxit smtp get"
      },
      {
        "title": "Node.js",
        "text": "Install nodemailer separately. Supply your key from the server environment. Use a verified sender and your recipient’s address.",
        "code": "import nodemailer from 'nodemailer';\n\n\n\nconst smtp = nodemailer.createTransport({\n\n\n\n  host: 'mail.inboxit.wtf', port: 587, secure: false, requireTLS: true,\n\n\n\n  auth: {user: 'inboxit', pass: process.env.INBOXIT_API_KEY}\n\n\n\n});\n\n\n\nawait smtp.sendMail({from: 'Your Brand <hello@mail.yourbrand.com>',\n\n\n\n  to: 'recipient@example.com', subject: 'Welcome', text: 'Your account is ready.'});"
      },
      {
        "title": "Supabase",
        "text": "Enter these settings in custom SMTP, with your verified sender and display name. Configure auth redirect URLs for your app separately. The password is an InboxIt key, not a Supabase service-role key. The auth provider may enforce its own email limits."
      },
      {
        "title": "Limits and errors",
        "text": "One recipient, 100,000 raw bytes, no attachments. Envelope sender must match From. Same sender/quota/suppression/account checks as REST. Success means queued. Identical raw submissions use a content-derived idempotency key. 535: authentication; 452: recipients; 552: size; 553: sender mismatch; 554: attachments; 451: temporary failure; 550: application rejection."
      }
    ]
  },
  {
    "slug": "billing",
    "title": "Plans & billing",
    "description": "Monthly subscriptions, confirmed payments and account allowances.",
    "group": "Guides",
    "sections": [
      {
        "title": "Plan changes",
        "text": "Choose a plan on Pricing and review the recurring ZAR amount in Settings → Billing. PayFast collects card payment. Confirmed payments activate your account allowance and issue a downloadable receipt. Cancel future renewals in Billing; paid access remains until the confirmed period ends. Existing plan changes require billing support. DIGIGAP TECHNOLOGIES is not VAT registered and charges no VAT."
      },
      {
        "title": "Read entitlements",
        "text": "billing get is an alias for GET /usage. It returns plan, volume, price and consumption, not invoices. Workspace admins cannot grant themselves paid plans. The owner’s plan controls shared limits.",
        "code": "inboxit billing get"
      }
    ]
  },
  {
    "slug": "teams",
    "title": "Workspaces & teams",
    "description": "Explicit roles and invitations that survive sign-up.",
    "group": "Guides",
    "sections": [
      {
        "title": "Workspace boundaries",
        "text": "Workspaces isolate resources, but account quotas are shared. Names are 1–10 characters; an account can own 20 workspaces.",
        "code": "inboxit workspaces list\ninboxit workspace use --id WORKSPACE_UUID"
      },
      {
        "title": "Invitations",
        "text": "Owners/admins invite admin or operator roles. Pending invitations persist after signup/sign-in. The matching verified email must explicitly accept.",
        "code": "inboxit team invite --email teammate@example.com --role operator\ninboxit invitations list\ninboxit invitations respond --id INVITATION_UUID --action accept"
      },
      {
        "title": "Role management",
        "text": "Admins manage members and invitations. Operators cannot administer keys, domains or members. Owner/self membership cannot be changed or removed through these endpoints.",
        "code": "inboxit team update-member --id MEMBER_UUID --role admin"
      }
    ]
  },
  {
    "slug": "errors",
    "title": "Errors & retries",
    "description": "Handle failures without duplicate messages.",
    "group": "Guides",
    "sections": [
      {
        "title": "Error body",
        "text": "JSON contains an error string; branch on HTTP status, not exact wording.",
        "code": "{\"error\":\"A valid Idempotency-Key is required\"}"
      },
      {
        "title": "Statuses",
        "text": "Creates normally return 201; inbox provisioning returns 202; other successes return 200.",
        "rows": [
          [
            "Status",
            "Meaning / action"
          ],
          [
            "400",
            "Invalid fields, cursor or idempotency key"
          ],
          [
            "401",
            "Authenticate or replace expired/revoked key"
          ],
          [
            "403",
            "Check scopes, role, workspace and eligibility"
          ],
          [
            "404",
            "Missing/inaccessible resource or unsupported route"
          ],
          [
            "409",
            "Conflict, plan limit or pending operation"
          ],
          [
            "413",
            "Reduce payload size"
          ],
          [
            "429",
            "Respect Retry-After and back off"
          ],
          [
            "503",
            "Temporarily unavailable; reconcile writes before retry"
          ]
        ]
      },
      {
        "title": "Rate limits",
        "text": "Account and edge limits apply. Backend 429 responses include Retry-After: 60. DNS checks have a ten-second guard. Use exponential backoff with jitter; a rate ceiling is not a delivery throughput guarantee."
      },
      {
        "title": "Write recovery",
        "text": "For sends/inbox creation reuse the original idempotency key and payload. For other writes read current state after ambiguous failures. Receiving-route 503 can mean pending durable work. Do not retry every 4xx."
      }
    ]
  },
  {
    "slug": "api-reference/introduction",
    "title": "API reference",
    "description": "Implemented routes, permissions and request contracts.",
    "group": "Guides",
    "sections": [
      {
        "title": "Base URL",
        "text": "https://inboxit.wtf/api/v2. JSON requests use Content-Type: application/json. Raw-message downloads return binary .eml content."
      },
      {
        "title": "Authentication",
        "text": "Scoped-key endpoints accept Authorization: Bearer <API key>. User-session routes are best called with the documented CLI command after inboxit login. Owner/admin routes reject ordinary workspace API keys."
      },
      {
        "title": "Pagination",
        "text": "Logs use an opaque before cursor. Messages use a UID next_before. Outgoing email lists return the last 100 with no pagination. There is no universal pagination contract."
      },
      {
        "title": "Examples",
        "text": "Identifiers and response values are illustrative. Unsupported methods are not implied by a resource name. Every endpoint below corresponds to a current backend route."
      }
    ]
  },
  {
    "slug": "anonymous-testing",
    "title": "Email testing without signup",
    "description": "Create a private temporary inbox using HTTP. No account, session, domain setup or CLI required.",
    "group": "Guides",
    "sections": [
      {
        "title": "Create an inbox",
        "text": "POST the public endpoint with a unique 16–128 character Idempotency-Key (letters, numbers, underscore or hyphen). No Authorization header is required. Save the returned token privately; reuse the same idempotency key on the same network only when retrying this creation.",
        "code": "curl -X POST 'https://inboxit.wtf/api/v2/public/inboxes' -H 'Idempotency-Key: signup-test-unique-001'"
      },
      {
        "title": "Trigger and read",
        "text": "Use the returned address in your application test. Read using the returned inbox token, not a workspace API key. Wait matches sender/subject substrings case-insensitively and message IDs greater than after. Read the last message ID before triggering the test to avoid matching an older message.",
        "code": "curl 'https://inboxit.wtf/api/v2/public/inboxes/wait?subject=Verify&after=0&timeout=20' -H \"Authorization: Bearer $INBOX_TOKEN\""
      },
      {
        "title": "Inspect the message",
        "text": "A matched wait includes the message. You can also list messages and retrieve an individual message by ID. Treat email content and extracted links as untrusted; only follow the expected application domain. A waiting result is not an error; wait again after poll_after_seconds."
      },
      {
        "title": "Delete and handle expiry",
        "text": "Receive-only: 24 hours from creation, up to 100 incoming emails and 10 MB per inbox. Up to three creations per network per UTC day and three active inboxes; browser/API share limits. Service-wide capacity also applies. Never put the secret token in URLs, logs or public code. DELETE the base endpoint using the inbox token when finished. Expired, removed or invalid inbox capabilities are unavailable; create a new inbox for a new test."
      },
      {
        "title": "Limits and retries",
        "text": "120 requests per network per minute. Only one wait per inbox; timeout is 1–20 seconds. Respect Retry-After on 429 and poll_after_seconds. Do not retry creation with a new key after a network failure: reuse the original key. This API cannot send email."
      }
    ]
  },
  {
    "slug": "api-reference/emails/get",
    "title": "Retrieve email",
    "description": "GET /api/v2/emails/{id}",
    "group": "API · emails",
    "sections": [
      {
        "title": "Authorization",
        "text": "emails:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/emails/RESOURCE_UUID' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit emails get --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"EMAIL_UUID\",\n  \"status\": \"delivered\",\n  \"track_opens\": true,\n  \"track_clicks\": true,\n  \"open_count\": 1,\n  \"click_count\": 0,\n  \"tracking_links\": []\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Response excerpt. Includes first opened_at/clicked_at timestamps and per-link url, clicks, first_clicked_at and last_clicked_at where tracked. Workspace and private inbox access rules apply. Tracking must be opted into when sending HTML; no retroactive tracking or direct SMTP tracking. No open/click webhook events yet. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/testing/list",
    "title": "List temporary inboxes",
    "description": "GET /api/v2/testing/inboxes",
    "group": "API · testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "inboxes:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/testing/inboxes' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit testing list"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"inboxes\": []\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Lists unexpired temporary inboxes, including pending/failed provisioning states. Available through the dashboard, API and CLI. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/testing/create",
    "title": "Create a temporary inbox",
    "description": "POST /api/v2/testing/inboxes",
    "group": "API · testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "inboxes:create. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "Required header: Idempotency-Key (1–100 alphanumeric, underscore or hyphen characters).",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "name",
            "string · required",
            "1–60 characters"
          ],
          [
            "ttl_seconds",
            "integer · optional",
            "60–86400; default 3600"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X POST 'https://inboxit.wtf/api/v2/testing/inboxes' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\" \\\n  -H \"Content-Type: application/json\" --data @request.json \\\n  -H \"Idempotency-Key: request-001\""
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"name\": \"Signup test\",\n  \"ttl_seconds\": 3600\n}"
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit testing create --data @request.json --idempotency-key request-001"
      },
      {
        "title": "Response",
        "text": "HTTP 201. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"INBOX_UUID\",\n  \"address\": \"agent-generated@agents.inboxit.wtf\",\n  \"status\": \"pending\",\n  \"test_expires_at\": \"2026-10-23T20:00:00Z\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Native provisioning is asynchronous. Poll list until active. Idempotency-Key required. Same key with changed parameters returns 409. Incoming volume and storage limits apply. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/testing/delete",
    "title": "Delete a temporary inbox",
    "description": "DELETE /api/v2/testing/inboxes/{id}",
    "group": "API · testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "inboxes:create. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X DELETE 'https://inboxit.wtf/api/v2/testing/inboxes/RESOURCE_UUID' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit testing delete --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"INBOX_UUID\",\n  \"deleted\": true\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Disables the temporary address, deletes its content and run records, and removes its credentials and replaces the native delivery route with a rejection marker. A cleanup failure is retried by the server timer. Permanent inboxes are rejected. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/testing/wait",
    "title": "Wait for a new email",
    "description": "POST /api/v2/testing/inboxes/{id}/wait",
    "group": "API · testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "messages:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ],
          [
            "sender",
            "string · optional",
            "Exact email address, case insensitive"
          ],
          [
            "subject",
            "string · optional",
            "Subject substring, case insensitive"
          ],
          [
            "timeout_seconds",
            "integer · optional",
            "1–300; default 60"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X POST 'https://inboxit.wtf/api/v2/testing/inboxes/RESOURCE_UUID/wait' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\" \\\n  -H \"Content-Type: application/json\" --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"subject\": \"Verify\",\n  \"timeout_seconds\": 60\n}"
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit testing wait --id RESOURCE_UUID --data @request.json"
      },
      {
        "title": "Response",
        "text": "HTTP 201. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"RUN_UUID\",\n  \"status\": \"waiting\",\n  \"after_id\": \"0\",\n  \"uid_validity\": \"1234\",\n  \"deadline\": \"2026-10-23T19:01:00Z\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Start BEFORE triggering your application. Existing messages are excluded using a mailbox UID boundary. API returns immediately; poll testing result. CLI waits and exits 2 on timeout. Inbox must be active (409 otherwise). Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/testing/result",
    "title": "Retrieve a test result",
    "description": "GET /api/v2/testing/runs/{id}",
    "group": "API · testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "messages:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/testing/runs/RESOURCE_UUID' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit testing result --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"RUN_UUID\",\n  \"status\": \"matched\",\n  \"matched_id\": \"1\",\n  \"extraction\": {\n    \"codes\": [\n      \"482951\"\n    ],\n    \"links\": [\n      \"https://example.com/confirm\"\n    ],\n    \"code\": \"482951\",\n    \"link\": \"https://example.com/confirm\",\n    \"ambiguous\": false,\n    \"untrusted_content\": true\n  }\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Response excerpt. Status is waiting, matched, timed_out or cancelled. Matched response includes plain-text message. Mailbox reset returns 409; expiry returns 410 or 404 after cleanup. Does not follow extracted links. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/testing/cancel",
    "title": "Cancel a wait",
    "description": "DELETE /api/v2/testing/runs/{id}",
    "group": "API · testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "messages:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X DELETE 'https://inboxit.wtf/api/v2/testing/runs/RESOURCE_UUID' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit testing cancel --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"RUN_UUID\",\n  \"status\": \"cancelled\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Cancels a waiting run; completed/missing runs return 404. Does not delete its inbox. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/testing/extract",
    "title": "Extract codes and links",
    "description": "GET /api/v2/testing/inboxes/{id}/messages/{message}/extract",
    "group": "API · testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "messages:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ],
          [
            "message",
            "path · required",
            "Positive mailbox UID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/testing/inboxes/RESOURCE_UUID/messages/42/extract' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit testing extract --id RESOURCE_UUID --message 42"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"codes\": [\n    \"482951\"\n  ],\n  \"links\": [],\n  \"code\": \"482951\",\n  \"link\": null,\n  \"ambiguous\": false,\n  \"untrusted_content\": true\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Extracts 4–8 digit candidates and HTTP/HTTPS links from a message in an active temporary inbox. Multiple candidates make the singular value null; maximum 30 per kind. Content is untrusted. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/emails/send",
    "title": "Send email",
    "description": "POST /api/v2/emails",
    "group": "API · emails",
    "sections": [
      {
        "title": "Authorization",
        "text": "emails:send. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "Required header: Idempotency-Key (1–100 alphanumeric, underscore or hyphen characters).",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "from",
            "string · required",
            "Bare sender email; active inbox or verified workspace domain"
          ],
          [
            "to",
            "string · required",
            "One recipient address"
          ],
          [
            "subject",
            "string · required",
            "Nonempty, at most 200 characters; no newlines"
          ],
          [
            "text",
            "string · required",
            "Nonempty plain text, at most 10,000 characters"
          ],
          [
            "html",
            "string · optional",
            "Up to 80,000 characters"
          ],
          [
            "tracking",
            "object · optional",
            "opens and clicks boolean flags, both default false; HTML only"
          ],
          [
            "from_name",
            "string · optional",
            "Display name up to 100 characters"
          ],
          [
            "reply_to",
            "string · optional",
            "Valid reply destination"
          ],
          [
            "in_reply_to",
            "string · optional",
            "RFC Message-ID including <angle brackets>"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X POST 'https://inboxit.wtf/api/v2/emails' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\" \\\n  -H \"Content-Type: application/json\" --data @request.json \\\n  -H \"Idempotency-Key: request-001\""
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"from\": \"hello@mail.yourbrand.com\",\n  \"to\": \"recipient@example.com\",\n  \"subject\": \"Welcome\",\n  \"text\": \"Thanks for joining.\",\n  \"html\": \"<h1>Welcome</h1><p>Thanks for joining.</p>\",\n  \"tracking\": {\n    \"opens\": true,\n    \"clicks\": true\n  }\n}"
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit emails send --data @request.json --idempotency-key request-001"
      },
      {
        "title": "Response",
        "text": "HTTP 201. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"EMAIL_UUID\",\n  \"status\": \"pending\",\n  \"message_id\": \"<id@mail.yourbrand.com>\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Idempotency-Key is required. Same key and payload returns the existing result; a changed payload returns 409. Account quotas, suppression, verified sender and account verification checks apply. 201 is queue acceptance, not delivery. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/emails/list",
    "title": "List emails",
    "description": "GET /api/v2/emails",
    "group": "API · emails",
    "sections": [
      {
        "title": "Authorization",
        "text": "emails:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/emails' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit emails list"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"emails\": []\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Returns the last 100 workspace outbound records, newest first. Each item has id, sender, recipient, subject, status, message_id and created_at. GET /emails/{id} returns one email. Tracking fields include track_opens, track_clicks, opened_at, clicked_at, open_count, click_count and tracking_links. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/domains/list",
    "title": "List domains",
    "description": "GET /api/v2/domains",
    "group": "API · domains",
    "sections": [
      {
        "title": "Authorization",
        "text": "emails:read or user session. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/domains' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit domains list"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"allowance\": {\n    \"domain_limit\": 1,\n    \"domains_used\": 0,\n    \"can_add_domain\": true\n  },\n  \"domains\": []\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Allowance also includes plan entitlements. Domains contain id, name, status, checks, checked_at, created_at and records. Pending domains count toward the account limit. Example allowance is an excerpt. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/domains/add",
    "title": "Add domain",
    "description": "POST /api/v2/domains",
    "group": "API · domains",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "name",
            "string · required",
            "Public domain or subdomain, no URL/path/email, maximum 253 characters"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit domains add --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"name\": \"mail.yourbrand.com\"\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 201. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"DOMAIN_UUID\",\n  \"name\": \"mail.yourbrand.com\",\n  \"status\": \"pending\",\n  \"records\": [\n    {\n      \"purpose\": \"ownership\",\n      \"type\": \"TXT\",\n      \"host\": \"_inboxit.mail.yourbrand.com\",\n      \"value\": \"inboxit-verification=GENERATED_TOKEN\",\n      \"required\": true\n    }\n  ]\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Response excerpt: actual records also include generated DKIM and recommended DMARC. Copy returned values, never example tokens. Existing workspace domain returns its record; exhausted plan or conflicting domain returns 409. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/domains/verify",
    "title": "Verify domain",
    "description": "POST /api/v2/domains/{id}/verify",
    "group": "API · domains",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit domains verify --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"DOMAIN_UUID\",\n  \"name\": \"mail.yourbrand.com\",\n  \"status\": \"verified\",\n  \"checks\": {},\n  \"checked_at\": \"2026-10-23T12:00:00Z\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Response excerpt; also returns records and created_at. Resolves ownership and DKIM TXT. DMARC is recommended, not required. Checking within ten seconds returns 429; otherwise failed DNS checks leave status pending. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/domains/provider",
    "title": "Detect DNS provider",
    "description": "GET /api/v2/domains/{id}/provider",
    "group": "API · domains",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit domains provider --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"provider\": null,\n  \"nameservers\": [],\n  \"zone\": null,\n  \"status\": \"unknown\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Best-effort lookup: status is found, unknown or unavailable. Detected provider has name and url; nameservers is a string array and zone is the resolved zone. Does not edit DNS. Use the dashboard or inspect the returned result for provider navigation. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/domains/delete",
    "title": "Delete domain",
    "description": "DELETE /api/v2/domains/{id}",
    "group": "API · domains",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit domains delete --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"removed\": true\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "409 if any receiving address still uses the domain. Remove its receiving routes first. Domain deletion removes sending authorization. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/inboxes/list",
    "title": "List inboxes",
    "description": "GET /api/v2/inboxes",
    "group": "API · inboxes",
    "sections": [
      {
        "title": "Authorization",
        "text": "inboxes:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/inboxes' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit inboxes list"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"inboxes\": []\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Items: id, name, address, status, receiving_address, receiving_status, created_at. Wait until status active before message access or custom address assignment. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/inboxes/create",
    "title": "Create inbox",
    "description": "POST /api/v2/inboxes",
    "group": "API · inboxes",
    "sections": [
      {
        "title": "Authorization",
        "text": "inboxes:create. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "Required header: Idempotency-Key (1–100 alphanumeric, underscore or hyphen characters).",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "name",
            "string · required",
            "1–60 characters"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X POST 'https://inboxit.wtf/api/v2/inboxes' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\" \\\n  -H \"Content-Type: application/json\" --data @request.json \\\n  -H \"Idempotency-Key: request-001\""
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"name\": \"Support\"\n}"
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit inboxes create --data @request.json --idempotency-key request-001"
      },
      {
        "title": "Response",
        "text": "HTTP 202. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"INBOX_UUID\",\n  \"name\": \"Support\",\n  \"address\": \"agent-generated@agents.inboxit.wtf\",\n  \"status\": \"pending\",\n  \"created_at\": \"2026-10-23T12:00:00Z\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Idempotency-Key required (1–100 letters/digits/_/-). Same key with different name returns 409. Provisioning runs asynchronously. Unlimited inboxes on every plan; volume and storage quotas still apply. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/inboxes/address",
    "title": "Assign receiving address",
    "description": "POST /api/v2/inboxes/{id}/receiving-address",
    "group": "API · inboxes",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ],
          [
            "address",
            "string · required",
            "Complete email, maximum 254 characters; local part maximum 64"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit inboxes address --id RESOURCE_UUID --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"address\": \"hello@mail.yourbrand.com\"\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"INBOX_UUID\",\n  \"address\": \"hello@mail.yourbrand.com\",\n  \"status\": \"active\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Assigns or renames the receiving address on an active inbox. Domain must be verified in this workspace and MX must point exclusively to mail.inboxit.wtf. Routing 503 may mean a pending persisted change; inspect receiving_status. A conflicting pending change returns 409. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/inboxes/remove-address",
    "title": "Remove receiving address",
    "description": "DELETE /api/v2/inboxes/{id}/receiving-address",
    "group": "API · inboxes",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit inboxes remove-address --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"INBOX_UUID\",\n  \"address\": null,\n  \"status\": \"none\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Removes the custom route through durable cleanup. Does not delete the inbox or its stored messages. Reconcile pending routing after a temporary failure. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/inboxes/sent",
    "title": "List sent messages",
    "description": "GET /api/v2/inboxes/{id}/sent",
    "group": "API · inboxes",
    "sections": [
      {
        "title": "Authorization",
        "text": "messages:read AND emails:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/inboxes/RESOURCE_UUID/sent' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit inboxes sent --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"messages\": []\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Returns sent messages associated with the selected inbox, including stored outbound content. The inbox must belong to this workspace. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/messages/list",
    "title": "List messages",
    "description": "GET /api/v2/inboxes/{id}/messages",
    "group": "API · messages",
    "sections": [
      {
        "title": "Authorization",
        "text": "messages:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ],
          [
            "limit",
            "query integer · optional",
            "1–50, default 20"
          ],
          [
            "before",
            "query UID · optional",
            "Positive mailbox UID; use next_before from the previous page"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/inboxes/RESOURCE_UUID/messages?limit=20' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit messages list --id RESOURCE_UUID --query '{\"limit\":\"20\"}'"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"uid_validity\": \"123456\",\n  \"messages\": [],\n  \"next_before\": null\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Requires an active inbox (409 otherwise). Scope persisted UIDs by inbox and uid_validity. null next_before ends pagination. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/messages/get",
    "title": "Retrieve message",
    "description": "GET /api/v2/inboxes/{id}/messages/{message}",
    "group": "API · messages",
    "sections": [
      {
        "title": "Authorization",
        "text": "messages:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ],
          [
            "message",
            "path · required",
            "Positive mailbox UID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/inboxes/RESOURCE_UUID/messages/42' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit messages get --id RESOURCE_UUID --message 42"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"42\",\n  \"subject\": \"Re: Hello\",\n  \"from\": \"recipient@example.com\",\n  \"to\": \"hello@mail.yourbrand.com\",\n  \"date\": \"Fri, 23 Oct 2026 12:00:00 +0000\",\n  \"message_id\": \"<reply@example.com>\",\n  \"in_reply_to\": \"<original@mail.yourbrand.com>\",\n  \"references\": \"<original@mail.yourbrand.com>\",\n  \"received_at\": \"2026-10-23T12:00:00+00:00\",\n  \"text\": \"Thanks!\",\n  \"attachments\": [],\n  \"untrusted_content\": true\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "The message path parameter is a positive mailbox UID, not an outgoing email UUID. Missing message returns 404. Use raw download when exact MIME source is needed. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/messages/raw",
    "title": "Download raw message",
    "description": "GET /api/v2/inboxes/{id}/messages/{message}/raw",
    "group": "API · messages",
    "sections": [
      {
        "title": "Authorization",
        "text": "messages:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ],
          [
            "message",
            "path · required",
            "Positive mailbox UID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/inboxes/RESOURCE_UUID/messages/42/raw' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit messages raw --id RESOURCE_UUID --message 42"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "Binary RFC email source (.eml), Content-Type: application/octet-stream."
      },
      {
        "title": "Behavior & errors",
        "text": "Save bytes directly; do not JSON-parse this response. CLI --output refuses to overwrite an existing file. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/analytics/get",
    "title": "Retrieve analytics",
    "description": "GET /api/v2/analytics",
    "group": "API · analytics",
    "sections": [
      {
        "title": "Authorization",
        "text": "emails:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "days",
            "query integer · optional",
            "7, 30 or 90; default 30"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/analytics?days=30' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit analytics get --query '{\"days\":\"30\"}'"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"days\": 30,\n  \"timezone\": \"UTC\",\n  \"series\": [\n    {\n      \"day\": \"2026-10-23\",\n      \"sent\": 2,\n      \"delivered\": 1,\n      \"bounced\": 0,\n      \"failed\": 0,\n      \"received\": 1\n    }\n  ],\n  \"totals\": {\n    \"sent\": 2,\n    \"delivered\": 1,\n    \"bounced\": 0,\n    \"failed\": 0,\n    \"received\": 1\n  }\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Example series is shortened. Workspace-scoped; outbound grouped by creation day and current status. Also returns open_tracked, click_tracked, opened, clicked, opens and clicks in totals and series, plus up to 100 recent emails with per-link counts. opened/clicked count unique emails; opens/clicks count events. Rates use tracked emails as denominators. Events are grouped by email creation day, not event day. Proxies/scanners can inflate counts; image blocking can hide opens. Native provider failures may count as failed instead of bounced. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/logs/list",
    "title": "List logs",
    "description": "GET /api/v2/logs",
    "group": "API · logs",
    "sections": [
      {
        "title": "Authorization",
        "text": "emails:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "status",
            "query enum · optional",
            "all, pending, queued, delivered, bounced, failed, uncertain, received"
          ],
          [
            "limit",
            "query integer · optional",
            "1–100, default 50"
          ],
          [
            "before",
            "query string · optional",
            "Opaque next cursor from previous response"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/logs?status=all&limit=50' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit logs list --query '{\"status\":\"all\",\"limit\":\"50\"}'"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"items\": [],\n  \"next\": null\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Items: id, email_id, status, recipient, subject, created_at, delivered_at, failure_code, attempts. Incoming email_id/subject can be null. Newest first; next=null ends pagination. No message bodies. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/usage/get",
    "title": "Retrieve usage",
    "description": "GET /api/v2/usage",
    "group": "API · usage",
    "sections": [
      {
        "title": "Authorization",
        "text": "emails:read. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/usage' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit usage get"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"plan\": \"free\",\n  \"name\": \"Free\",\n  \"domain_limit\": 1,\n  \"daily_limit\": 100,\n  \"monthly_limit\": 1000,\n  \"incoming_limit\": 1000,\n  \"storage_limit\": 104857600,\n  \"retention_days\": 7,\n  \"inbox_limit\": null,\n  \"price\": 0,\n  \"daily_used\": 0,\n  \"monthly_used\": 0,\n  \"incoming_used\": 0,\n  \"sending_paused\": false,\n  \"pause_reason\": null,\n  \"mode\": \"native\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Account-wide, shared across workspaces. Counters use UTC day/month. Outgoing counts submitted rows, not only successful delivery. Incoming allowance is separate. null inbox_limit means unlimited. Does not return current storage bytes or invoices. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/smtp/get",
    "title": "Retrieve SMTP settings",
    "description": "GET /api/v2/smtp",
    "group": "API · smtp",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated API key or user session. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/smtp' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit smtp get"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"host\": \"mail.inboxit.wtf\",\n  \"port\": 587,\n  \"encryption\": \"STARTTLS\",\n  \"username\": \"inboxit\",\n  \"password\": \"Use a workspace API key with emails:send scope\",\n  \"max_recipients\": 1,\n  \"max_bytes\": 100000,\n  \"attachments\": false\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Returns connection instructions, not a secret. Create a dedicated emails:send key for SMTP. See the SMTP guide for limits and Supabase setup. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/webhooks/list",
    "title": "List webhooks",
    "description": "GET /api/v2/webhooks",
    "group": "API · webhooks",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit webhooks list"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"endpoints\": [],\n  \"deliveries\": []\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Endpoints: id, url, events, enabled, created_at. Deliveries: id, endpoint_id, type, state, attempts, last_status, last_error, next_attempt, updated_at. Last 100 deliveries. Secrets never appear. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/webhooks/create",
    "title": "Create webhook",
    "description": "POST /api/v2/webhooks",
    "group": "API · webhooks",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "url",
            "string · required",
            "Public HTTPS port 443; no private destinations/redirects"
          ],
          [
            "events",
            "string[] · required",
            "Nonempty subset: email.delivered, email.bounced, email.received"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit webhooks create --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"url\": \"https://yourbrand.com/hooks/inboxit\",\n  \"events\": [\n    \"email.delivered\",\n    \"email.bounced\",\n    \"email.received\"\n  ]\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 201. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"ENDPOINT_UUID\",\n  \"secret\": \"ONE_TIME_SIGNING_SECRET\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Five active endpoints per workspace. Store the secret immediately. See the webhook guide for raw-body signature verification and retries. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/webhooks/delete",
    "title": "Delete webhook",
    "description": "DELETE /api/v2/webhooks/{id}",
    "group": "API · webhooks",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit webhooks delete --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"disabled\": true\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Disables rather than erases the endpoint and cancels queued deliveries. An in-flight request may still arrive. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/webhooks/retry",
    "title": "Retry webhook delivery",
    "description": "POST /api/v2/webhook-deliveries/{id}/retry",
    "group": "API · webhooks",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit webhooks retry --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"queued\": true\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Path id is a delivery ID, not endpoint/event ID. Only failed deliveries on enabled workspace endpoints can be retried. Resets attempts and queues immediately; otherwise 404. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/keys/list",
    "title": "List keys",
    "description": "GET /api/v2/keys",
    "group": "API · keys",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit keys list"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"keys\": []\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Key metadata: id, name, prefix, scopes, created_at, expires_at, revoked_at. Operators receive an empty list. Tokens are never returned here. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/keys/create",
    "title": "Create API key",
    "description": "POST /api/v2/keys",
    "group": "API · keys",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "name",
            "string · required",
            "1–60 characters"
          ],
          [
            "scopes",
            "string[] · required",
            "Nonempty supported scopes; see Authentication"
          ],
          [
            "expires_in_days",
            "integer · optional",
            "1–365, default 30"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit keys create --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"name\": \"Backend\",\n  \"scopes\": [\n    \"emails:send\",\n    \"emails:read\"\n  ],\n  \"expires_in_days\": 30\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 201. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"KEY_UUID\",\n  \"name\": \"Backend\",\n  \"prefix\": \"iit_…\",\n  \"scopes\": [\n    \"emails:send\",\n    \"emails:read\"\n  ],\n  \"expires_at\": \"2026-11-22T12:00:00Z\",\n  \"token\": \"iit_ONE_TIME_SECRET\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Ten active keys per account. Save token once; it is not recoverable from list responses. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/keys/revoke",
    "title": "Revoke API key",
    "description": "DELETE /api/v2/keys/{id}",
    "group": "API · keys",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit keys revoke --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"KEY_UUID\",\n  \"revoked\": true\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Revokes the selected workspace key, including SMTP access. Repeated revocation is safe. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/workspaces/list",
    "title": "List workspaces",
    "description": "GET /api/v2/workspaces",
    "group": "API · workspaces",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit workspaces list"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"workspaces\": [],\n  \"activeWorkspaceId\": \"WORKSPACE_UUID\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Workspace items: id, name, created_at, role. Includes owned workspaces and memberships. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/workspaces/create",
    "title": "Create workspace",
    "description": "POST /api/v2/workspaces",
    "group": "API · workspaces",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "name",
            "string · required",
            "Trimmed 1–10 characters"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit workspaces create --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"name\": \"prod\"\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 201. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"WORKSPACE_UUID\",\n  \"name\": \"prod\",\n  \"created_at\": \"2026-10-23T12:00:00Z\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Maximum 20 owned workspaces. Account quotas are shared, not reset by creating a workspace. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/workspaces/update",
    "title": "Update workspace",
    "description": "PATCH /api/v2/workspace",
    "group": "API · workspaces",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "name",
            "string · required",
            "Trimmed 1–10 characters"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit workspaces update --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"name\": \"prod\"\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"WORKSPACE_UUID\",\n  \"name\": \"prod\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Updates the selected workspace. There is no workspace deletion endpoint. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/profile/get",
    "title": "Retrieve profile",
    "description": "GET /api/v2/profile",
    "group": "API · profile",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit profile get"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"display_name\": \"Your Name\",\n  \"avatar\": null,\n  \"identity_provider\": \"supabase\",\n  \"created_at\": \"2026-10-23T12:00:00Z\",\n  \"is_admin\": false\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Returns the signed-in user profile. is_admin is platform administration, not the workspace role. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/profile/update",
    "title": "Update profile",
    "description": "PATCH /api/v2/profile",
    "group": "API · profile",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "name",
            "string · required",
            "Trimmed 1–80 characters"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit profile update --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"name\": \"Your Name\"\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"display_name\": \"Your Name\",\n  \"avatar\": null\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Updates display name, not email or password. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/profile/photo",
    "title": "Update profile photo",
    "description": "PATCH /api/v2/profile/photo",
    "group": "API · profile",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "avatar",
            "string or null · required",
            "JPEG data URL under 150 KB; null removes photo"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit profile photo --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"avatar\": null\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"display_name\": \"Your Name\",\n  \"avatar\": null\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "JPEG signature is checked. No PNG upload or multipart endpoint. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/account/get",
    "title": "Retrieve account",
    "description": "GET /api/v2/account",
    "group": "API · account",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated API key or user session. Use a workspace-scoped bearer key or an authorized user session."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Set INBOXIT_API_KEY in your server environment. The CLI can also use an authenticated user session.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/account' \\\n  -H \"Authorization: Bearer $INBOXIT_API_KEY\""
      },
      {
        "title": "CLI equivalent",
        "text": "Use INBOXIT_TOKEN for a scoped key, or inboxit login for a user session.",
        "code": "inboxit account get"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"ACCOUNT_UUID\",\n  \"inbox_limit\": null,\n  \"created_at\": \"2026-10-23T12:00:00Z\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Legacy account metadata. Use /usage for current plan entitlements; inbox_limit here is not the authoritative plan quota. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/notifications/list",
    "title": "List notifications",
    "description": "GET /api/v2/notifications",
    "group": "API · notifications",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit notifications list"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"events\": []\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Latest 30 workspace audit events with id, action, created_at. Not a webhook event stream. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/team/list",
    "title": "List team",
    "description": "GET /api/v2/team",
    "group": "API · team",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit team list"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"actor_id\": \"USER_UUID\",\n  \"role\": \"owner\",\n  \"workspace\": \"prod\",\n  \"members\": [],\n  \"invitations\": []\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Members include id, display_name, email and role. Pending invitations are visible to owner/admin only. workspace is the display name, not an object. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/team/invite",
    "title": "Invite a member",
    "description": "POST /api/v2/team/invites",
    "group": "API · team",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "email",
            "string · required",
            "Invitee email"
          ],
          [
            "role",
            "enum · optional",
            "admin or operator; default operator"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit team invite --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"email\": \"teammate@example.com\",\n  \"role\": \"operator\"\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 201. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"id\": \"INVITATION_UUID\",\n  \"mail_status\": \"pending\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "20 invitations per day per inviter. Existing membership conflicts with 409. Pending invitations persist through signup and require explicit acceptance by the matching verified email. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/team/revoke-invite",
    "title": "Revoke invitation",
    "description": "DELETE /api/v2/team/invites/{id}",
    "group": "API · team",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit team revoke-invite --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"revoked\": true\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Only pending invitations can be revoked; missing/nonpending returns 404. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/team/update-member",
    "title": "Update member role",
    "description": "PATCH /api/v2/team/members/{id}",
    "group": "API · team",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ],
          [
            "role",
            "enum · required",
            "admin or operator"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit team update-member --id RESOURCE_UUID --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"role\": \"operator\"\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"user_id\": \"USER_UUID\",\n  \"role\": \"operator\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Cannot change owner or your own role. ID is the member user ID. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/team/remove-member",
    "title": "Remove member",
    "description": "DELETE /api/v2/team/members/{id}",
    "group": "API · team",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit team remove-member --id RESOURCE_UUID"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"removed\": true\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Cannot remove owner or yourself. Removes membership access to this workspace. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/invitations/list",
    "title": "List invitations",
    "description": "GET /api/v2/invitations",
    "group": "API · invitations",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit invitations list"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"invitations\": [\n    {\n      \"id\": \"INVITATION_UUID\",\n      \"role\": \"operator\",\n      \"expires_at\": \"2026-10-30T12:00:00Z\",\n      \"workspace_name\": \"prod\",\n      \"inviter_email\": \"owner@example.com\"\n    }\n  ]\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Discovers invitations matching the authenticated email after signup/sign-in; no automatic acceptance. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/invitations/respond",
    "title": "Respond to invitation",
    "description": "POST /api/v2/invitations/{id}",
    "group": "API · invitations",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authenticated user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "id",
            "path · required",
            "Resource UUID"
          ],
          [
            "action",
            "enum · required",
            "accept or decline"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit invitations respond --id RESOURCE_UUID --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"action\": \"accept\"\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"workspace_id\": \"WORKSPACE_UUID\",\n  \"status\": \"accepted\"\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Requires the matching verified email. Acceptance is idempotent for an already accepted invitation. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/suppressions/add",
    "title": "Add suppression",
    "description": "POST /api/v2/suppressions",
    "group": "API · suppressions",
    "sections": [
      {
        "title": "Authorization",
        "text": "Owner/admin user session (use inboxit login). Use the CLI login flow; a workspace API key cannot call this operation."
      },
      {
        "title": "Parameters",
        "text": "All resource access is checked against the selected workspace and user permissions.",
        "rows": [
          [
            "Name",
            "Type",
            "Contract"
          ],
          [
            "recipient",
            "string · required",
            "Email address up to 254 characters"
          ]
        ]
      },
      {
        "title": "Request",
        "text": "Run inboxit login first. The CLI supplies authenticated user credentials.",
        "code": "inboxit suppressions add --data @request.json"
      },
      {
        "title": "JSON body",
        "text": "Save this JSON as request.json for the request above. Replace example values with your own.",
        "code": "{\n  \"recipient\": \"recipient@example.com\"\n}"
      },
      {
        "title": "Response",
        "text": "HTTP 200. Example values are illustrative; excerpts are marked.",
        "code": "{\n  \"suppressed\": true\n}"
      },
      {
        "title": "Behavior & errors",
        "text": "Adds an account-wide manual suppression. No customer unsuppress endpoint exists. Applies across owner workspaces. Common errors: 400 invalid input, 401 unauthenticated, 403 insufficient permission, 404 missing/inaccessible resource, 409 conflict, 429 rate/usage limit, 503 service unavailable. See Errors & retries for recovery guidance."
      }
    ]
  },
  {
    "slug": "api-reference/public-testing/create",
    "title": "Create anonymous test inbox",
    "description": "POST /api/v2/public/inboxes",
    "group": "API · public testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "No authentication or signup required. Creation is rate-limited by network."
      },
      {
        "title": "Contract",
        "text": "Required Idempotency-Key: 16–128 letters, numbers, underscore or hyphen. No request body required. Returns HTTP 201 with address, token and poll_after_seconds."
      },
      {
        "title": "HTTP request",
        "text": "Use from an agent, test runner or HTTP client. No CLI required.",
        "code": "curl -X POST 'https://inboxit.wtf/api/v2/public/inboxes' -H 'Idempotency-Key: signup-test-unique-001'"
      },
      {
        "title": "Limits and errors",
        "text": "Receive-only: 24 hours from creation, up to 100 incoming emails and 10 MB per inbox. Up to three creations per network per UTC day and three active inboxes; browser/API share limits. Service-wide capacity also applies. Never put the secret token in URLs, logs or public code. 400 invalid parameters; 401 missing/invalid token; 404 unavailable resource; 410 expired resource where applicable; 429 rate/capacity limit (respect Retry-After); 503 unavailable. The complete walkthrough is under Guides → Email testing without signup."
      }
    ]
  },
  {
    "slug": "api-reference/public-testing/read",
    "title": "Read anonymous test inbox",
    "description": "GET /api/v2/public/inboxes",
    "group": "API · public testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authorization: Bearer INBOX_TOKEN, returned by creation. It grants access only to that inbox. No login, session or workspace API key required."
      },
      {
        "title": "Contract",
        "text": "Returns inbox information and message list."
      },
      {
        "title": "HTTP request",
        "text": "Use from an agent, test runner or HTTP client. No CLI required.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/public/inboxes' -H \"Authorization: Bearer $INBOX_TOKEN\""
      },
      {
        "title": "Limits and errors",
        "text": "Receive-only: 24 hours from creation, up to 100 incoming emails and 10 MB per inbox. Up to three creations per network per UTC day and three active inboxes; browser/API share limits. Service-wide capacity also applies. Never put the secret token in URLs, logs or public code. 400 invalid parameters; 401 missing/invalid token; 404 unavailable resource; 410 expired resource where applicable; 429 rate/capacity limit (respect Retry-After); 503 unavailable. The complete walkthrough is under Guides → Email testing without signup."
      }
    ]
  },
  {
    "slug": "api-reference/public-testing/message",
    "title": "Read a test message",
    "description": "GET /api/v2/public/inboxes/messages/{id}",
    "group": "API · public testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authorization: Bearer INBOX_TOKEN, returned by creation. It grants access only to that inbox. No login, session or workspace API key required."
      },
      {
        "title": "Contract",
        "text": "id is a positive numeric mailbox message ID. Returns message content."
      },
      {
        "title": "HTTP request",
        "text": "Use from an agent, test runner or HTTP client. No CLI required.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/public/inboxes/messages/1' -H \"Authorization: Bearer $INBOX_TOKEN\""
      },
      {
        "title": "Limits and errors",
        "text": "Receive-only: 24 hours from creation, up to 100 incoming emails and 10 MB per inbox. Up to three creations per network per UTC day and three active inboxes; browser/API share limits. Service-wide capacity also applies. Never put the secret token in URLs, logs or public code. 400 invalid parameters; 401 missing/invalid token; 404 unavailable resource; 410 expired resource where applicable; 429 rate/capacity limit (respect Retry-After); 503 unavailable. The complete walkthrough is under Guides → Email testing without signup."
      }
    ]
  },
  {
    "slug": "api-reference/public-testing/wait",
    "title": "Wait for a test email",
    "description": "GET /api/v2/public/inboxes/wait",
    "group": "API · public testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authorization: Bearer INBOX_TOKEN, returned by creation. It grants access only to that inbox. No login, session or workspace API key required."
      },
      {
        "title": "Contract",
        "text": "Optional query: after numeric message ID (default 0), sender substring (max 254), subject substring (max 200), timeout integer 1–20 (default 20). HTTP 200 status matched with message, or waiting with poll_after_seconds."
      },
      {
        "title": "HTTP request",
        "text": "Use from an agent, test runner or HTTP client. No CLI required.",
        "code": "curl -X GET 'https://inboxit.wtf/api/v2/public/inboxes/wait' -H \"Authorization: Bearer $INBOX_TOKEN\""
      },
      {
        "title": "Limits and errors",
        "text": "Receive-only: 24 hours from creation, up to 100 incoming emails and 10 MB per inbox. Up to three creations per network per UTC day and three active inboxes; browser/API share limits. Service-wide capacity also applies. Never put the secret token in URLs, logs or public code. 400 invalid parameters; 401 missing/invalid token; 404 unavailable resource; 410 expired resource where applicable; 429 rate/capacity limit (respect Retry-After); 503 unavailable. The complete walkthrough is under Guides → Email testing without signup."
      }
    ]
  },
  {
    "slug": "api-reference/public-testing/delete",
    "title": "Delete anonymous test inbox",
    "description": "DELETE /api/v2/public/inboxes",
    "group": "API · public testing",
    "sections": [
      {
        "title": "Authorization",
        "text": "Authorization: Bearer INBOX_TOKEN, returned by creation. It grants access only to that inbox. No login, session or workspace API key required."
      },
      {
        "title": "Contract",
        "text": "Deletes the inbox and its content. This cannot be undone."
      },
      {
        "title": "HTTP request",
        "text": "Use from an agent, test runner or HTTP client. No CLI required.",
        "code": "curl -X DELETE 'https://inboxit.wtf/api/v2/public/inboxes' -H \"Authorization: Bearer $INBOX_TOKEN\""
      },
      {
        "title": "Limits and errors",
        "text": "Receive-only: 24 hours from creation, up to 100 incoming emails and 10 MB per inbox. Up to three creations per network per UTC day and three active inboxes; browser/API share limits. Service-wide capacity also applies. Never put the secret token in URLs, logs or public code. 400 invalid parameters; 401 missing/invalid token; 404 unavailable resource; 410 expired resource where applicable; 429 rate/capacity limit (respect Retry-After); 503 unavailable. The complete walkthrough is under Guides → Email testing without signup."
      }
    ]
  }
]