{
  "opencollection": "1.0.0",
  "info": {
    "name": "Primitive Account Sending API",
    "version": "1.0.0"
  },
  "items": [
    {
      "info": {
        "name": "Sending",
        "type": "folder"
      },
      "items": [
        {
          "info": {
            "name": "Reply to an inbound email",
            "type": "http"
          },
          "http": {
            "method": "POST",
            "url": "https://api.primitive.dev/v1/emails/:id/reply",
            "headers": [
              {
                "name": "Idempotency-Key",
                "value": ""
              }
            ],
            "params": [
              {
                "name": "id",
                "value": "",
                "type": "path",
                "description": "Resource UUID"
              }
            ],
            "body": {
              "type": "json",
              "data": "{}"
            },
            "auth": {
              "type": "bearer",
              "token": "{{bearerToken}}"
            }
          },
          "docs": "Sends an outbound reply to the inbound email identified by `id`.\nThreading headers (`In-Reply-To`, `References`), recipient\nderivation (Reply-To, then From, then bare sender), and the\n`Re:` subject prefix are all derived server-side from the\nstored inbound row. The request body carries only the message\nbody, optional From override, optional attachments, and optional\n`wait` flag; passing any header or recipient override is\nrejected by the schema (`additionalProperties: false`).\n\nForwards through "
        },
        {
          "info": {
            "name": "List send-permission rules",
            "type": "http"
          },
          "http": {
            "method": "GET",
            "url": "https://api.primitive.dev/v1/send-permissions",
            "auth": {
              "type": "bearer",
              "token": "{{bearerToken}}"
            }
          },
          "docs": "Returns a flat list of rules describing every recipient the\ncaller may send to. Each rule has a `type`, a kind-specific\npayload, and a human-readable `description`. If any rule\nmatches the recipient, /send-mail will accept the send under\nthe recipient-scope check.\n\nThe endpoint is the answer to \"where can I send\" without\nexposing internal entitlement names. Agents that don't\nrecognize a `type` can still read the `description` prose\nand act on it.\n\nRule kinds, ordered broadest-first so an agent c"
        },
        {
          "info": {
            "name": "Send outbound email",
            "type": "http"
          },
          "http": {
            "method": "POST",
            "url": "https://api.primitive.dev/v1/send-mail",
            "headers": [
              {
                "name": "Idempotency-Key",
                "value": ""
              }
            ],
            "body": {
              "type": "json",
              "data": "{}"
            },
            "auth": {
              "type": "bearer",
              "token": "{{bearerToken}}"
            }
          },
          "docs": "Sends an outbound email through Primitive's outbound relay. By default\nthe request returns once the relay accepts the message for delivery.\nSet `wait: true` to wait for the first downstream SMTP delivery outcome.\n\n**Host routing.** /send-mail is served by the canonical API host\n(`https://api.primitive.dev/v1`) so the request body can carry\ninline attachments up to ~30 MiB raw. The legacy dashboard\ncompatibility host (`https://www.primitive.dev/api/v1`) also accepts\n/send-mail, but Vercel request"
        },
        {
          "info": {
            "name": "List outbound sent emails",
            "type": "http"
          },
          "http": {
            "method": "GET",
            "url": "https://api.primitive.dev/v1/sent-emails",
            "params": [
              {
                "name": "cursor",
                "value": "",
                "type": "query",
                "description": "Pagination cursor from a previous response's `meta.cursor` field.\nFormat: `{ISO-datetime}|{id}`\n"
              },
              {
                "name": "limit",
                "value": "",
                "type": "query",
                "description": "Number of results per page"
              },
              {
                "name": "status",
                "value": "",
                "type": "query",
                "description": "Filter to rows in this status. Useful for polling\nqueued rows that haven't transitioned, auditing\ngate-denied attempts, or listing only successful\ndeliveries.\n"
              },
              {
                "name": "request_id",
                "value": "",
                "type": "query",
                "description": "Filter to the row matching a specific server-issued\n`request_id`. The /send-mail response surfaces\n`request_id` on every send; this lookup lets the\ncaller find the historical row for a given live call\nwithout remembering its `id`.\n"
              },
              {
                "name": "idempotency_key",
                "value": "",
                "type": "query",
                "description": "Filter to rows with the given `client_idempotency_key`.\nMultiple rows can share a key (a retry that hit the\nidempotent-replay path returns the same row, but a\nretry with a DIFFERENT canonical payload under the\nsame key is rejected by /send-mail before the row is\nwritten, so duplicates are bounded).\n"
              },
              {
                "name": "date_from",
                "value": "",
                "type": "query",
                "description": "Inclusive lower bound on `created_at`."
              },
              {
                "name": "date_to",
                "value": "",
                "type": "query",
                "description": "Inclusive upper bound on `created_at`."
              }
            ],
            "auth": {
              "type": "bearer",
              "token": "{{bearerToken}}"
            }
          },
          "docs": "Returns a paginated list of OUTBOUND emails the caller's\norg has sent via /send-mail (and /emails/{id}/reply, which\nforwards through /send-mail). Includes every recorded\nattempt, including gate-denied attempts that the agent\nnever called and rows still in `queued` state.\n\nFor inbound mail received at your verified domains, see\n/emails. There is no unified send/receive history endpoint;\nthe two surfaces are intentionally separate because the\nunderlying tables, statuses, and lifecycle differ.\n\nEma"
        },
        {
          "info": {
            "name": "Get a sent email by id",
            "type": "http"
          },
          "http": {
            "method": "GET",
            "url": "https://api.primitive.dev/v1/sent-emails/:id",
            "params": [
              {
                "name": "id",
                "value": "",
                "type": "path",
                "description": "Resource UUID"
              }
            ],
            "auth": {
              "type": "bearer",
              "token": "{{bearerToken}}"
            }
          },
          "docs": "Returns the full sent-email record by id, including\n`body_text` and `body_html` (omitted from the listing\nendpoint to keep paginated responses small). Use this when\ndiagnosing a specific send, e.g. inspecting the receiver's\nSMTP response on a `bounced` row or pulling the gate\ndenial detail on a `gate_denied` row.\n"
        },
        {
          "info": {
            "name": "Try send-mail without authentication (simulation)",
            "type": "http"
          },
          "http": {
            "method": "POST",
            "url": "https://api.primitive.dev/v1/send-mail/demo",
            "headers": [
              {
                "name": "Idempotency-Key",
                "value": ""
              }
            ],
            "body": {
              "type": "json",
              "data": "{}"
            }
          },
          "docs": "Unauthenticated sandbox for `POST /send-mail`. Accepts the same request body, validates it identically, and returns a realistic synthetic success envelope with `demo: true`. **No email is sent, queued, or stored.** Use this to exercise the send flow without credentials; to send real mail, sign up at https://primitive.dev/signup for an API key and call `POST /send-mail` with `Authorization: Bearer prim_<key>`."
        },
        {
          "info": {
            "name": "Send a batch of emails in one request",
            "type": "http"
          },
          "http": {
            "method": "POST",
            "url": "https://api.primitive.dev/v1/send-mail/batch",
            "headers": [
              {
                "name": "Idempotency-Key",
                "value": ""
              }
            ],
            "body": {
              "type": "json",
              "data": "{}"
            },
            "auth": {
              "type": "bearer",
              "token": "{{bearerToken}}"
            }
          },
          "docs": "Send up to 100 independent messages in a single call. Each message uses the same body schema and the same send path as `POST /send-mail`, so auth, validation, rate limiting, and idempotency apply per message. Messages are processed independently: one failing does not fail the others — every message gets an entry in `results` carrying either `data` (on success) or `error` (on failure), with the original `index`."
        }
      ]
    }
  ],
  "bundled": true
}