---
title: "Create an inbox (idempotent on requested username)"
method: POST
path: "/v1/inboxes"
tags: ["Inboxes"]
---

# Create an inbox (idempotent on requested username)

`POST /v1/inboxes`

## Request

- Base URL: `https://anjal.app`
- URL: `https://anjal.app/v1/inboxes`
- Auth: API key in header `X-API-Key`

Requires tenant master or workspace master key.

## Username allocation
- If `username` is set and your tenant **already** has an inbox at
  `username@domain`, returns that inbox (HTTP **200**, body
  contains `existed: true`). The call is idempotent — safe to
  retry.
- Otherwise tries to create `username@domain`. If the global
  username is taken by another tenant, falls back to
  `username1`, `username2`, … through `username99`. The actual
  allocated username is in the response body.
- Pass `?strict=true` to disable auto-fallback. With strict mode,
  a global collision returns HTTP **409** with the conflicting
  resource info instead of suffixing.

IMAP/SMTP credentials — `apiKey` and `imapPassword` — are only
returned on first creation, never on idempotent returns.

## Query parameters

- `strict` boolean

## Request body

- object
  - `username` string: Lowercase alphanumeric + `.-_`. Auto-generated from the tenant name if omitted. **No tenant-id suffix is appended** — collisions are resolved via sequential numeric fallback (e.g. `scout`, `scout1`, `scout2`).
  - `displayName` string
  - `domain` string: Defaults to anjal.app
  - `workspaceId` string, uuid: (Tenant master only) target workspace. Defaults to the tenant's default workspace.

## Response `200`

Idempotent return — your tenant already has an inbox at the
requested `username@domain`. `existed: true` is set on the
body. `apiKey` and `imapPassword` are NOT re-issued.

- Inbox
  - `id` string, uuid
  - `email` string: Current primary outbound address — may be a custom-domain alias.
  - `canonicalEmail` string: Stable identity used for IMAP/SMTP auth. Never changes after creation.
  - `username` string
  - `domain` string
  - `displayName` string
  - `workspaceId` string, uuid
  - `addresses` InboxAddress[]
    - `address` string
    - `isPrimary` boolean
  - `imapPassword` string: Only returned on creation and GET /inboxes/{id}. Stored plaintext so IMAP clients can log in.
  - `imap` ImapCreds
    - `host` string
    - `port` integer
    - `tls` boolean
    - `username` string
    - `password` string
  - `smtp` SmtpCreds
    - `host` string
    - `port` integer
    - `starttls` boolean
    - `username` string
    - `password` string
  - `createdAt` string, date-time

## Other responses

- `201`: Newly created. `apiKey` and `imapPassword` are returned once — store them now.
- `403`: Plan limit reached
- `409`: `USERNAME_TAKEN` — only returned when `?strict=true` is set and `username@domain` is taken globally. Body includes `requestedUsername`, `attemptedUsername`, and `domain` for single-round-trip recovery. Default behavior auto-falls back without ever returning 409.

---

[API](https://skmtc.dev/anjal/apis/anjal-api.md) · [All operations](https://skmtc.dev/anjal/apis/anjal-api/llms.txt) · [OpenAPI document](https://skmtc.dev/anjal/apis/anjal-api/revisions/a4044778e294?raw)
