# CommsHarbor — full API reference > Generated from the catalog at https://staging.commsharbor.com · build `ef1ee6a8` > 100 endpoints · 20 structures > Short index: https://staging.commsharbor.com/llms.txt · Spec: https://staging.commsharbor.com/openapi.json · MCP: https://staging.commsharbor.com/mcp > Manage domain email, webmail, mailboxes and aliases within each organization. > English is the default product language; the human UI is also available in pt-BR. > Free Trial lasts seven days and shares 1 GB across unlimited receive-only mailboxes on one domain. No outgoing SMTP, card or automatic conversion. Check activation_ready before starting. > Three monthly packages include storage allowances. Enterprise services have activation on demand. - [Also available on PayAPI Market](https://payapi.market/api/commsharbor) ## Free and paid services - [Free allowances and current prices](https://staging.commsharbor.com/api/pricing) - [Payment methods and conditions](https://staging.commsharbor.com/api/billing) - [First request and payment recovery](https://staging.commsharbor.com/skill.md) ## How to read - Every endpoint lists path, auth, parameters, body, response structure, errors and a call that runs. - `Pagina` is a reference: the fields are under **Structures**, at the end, once. - `(optional)` on a field means it may be absent; `(may be null)` means it comes with a null value. - Slice what you need: `https://staging.commsharbor.com/llms-full.txt?prefix=/api/` returns only that branch. ## Authentication - `credito` — Credit token in `Authorization: Bearer cred_…` or `X-Credito`. For recovered x402 funds, use the wallet credential mmw_… in Bearer or X-Wallet-Token, issued through /api/auth/wallet/agent/start and /api/auth/wallet/agent/token. - `none` — Public endpoint. No tenant data is returned. - `guest` — Temporary workspace of this browser (`POST /api/guest`): the HttpOnly `cm_guest` cookie, host-only, or the signed `cm_…` token in `X-Guest-Token` for an API client. It works without an account until `POST /api/auth/claim` attaches it to one; nothing signs anyone in automatically. - `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. - `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. - `organization_admin` — Owner or admin of the organization (shared-account roles), signed in with a second factor. Never an API key. - `platform_admin` — Session with an explicit platform_roles grant. Tenant ownership does not grant platform access. ## Endpoints ## Discovery ### `GET /agent.json` Agent card: identity, operator, documentation, the MCP endpoint and the tools it serves. Same document as `/.well-known/agent-card.json`. - **URL:** `https://staging.commsharbor.com/agent.json` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** `application/json`: `name`, `provider`, `protocol` (`mcp`), `interfaces[]` and `skills[]`. **Example** ```sh curl -s https://staging.commsharbor.com/agent.json ``` ### `GET /okf/:arquivo` OKF bundle (Open Knowledge Format v0.1): markdown with frontmatter so an agent reads the whole product without parsing HTML. - **URL:** `https://staging.commsharbor.com/okf/:arquivo` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Path parameters** - `arquivo` (string, required) — `index.md`, `sobre.md`, `api.md` or `faq.md`. e.g.: `index.md`. **Response `200`** `text/markdown`. Start at `/okf/index.md`, which lists the bundle. **Errors** - `404` — File outside the bundle. **Example** ```sh curl -s https://staging.commsharbor.com/okf/index.md ``` ### `GET /.well-known/:arquivo` Machine discovery before the home page: `api-catalog` (RFC 9727, a linkset with the API and the MCP), `security.txt` (RFC 9116), `x402` (payment manifest: network, wallet and the routes that charge) and `mcp-registry-auth` (the official MCP registry key). - **URL:** `https://staging.commsharbor.com/.well-known/:arquivo` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Path parameters** - `arquivo` (string, required) — `api-catalog`, `security.txt`, `x402`, `mcp-registry-auth` or `apis.json`. e.g.: `api-catalog`. **Response `200`** `application/linkset+json` for the api-catalog; `application/json` for x402 and apis.json; `text/plain` for the other two. **Errors** - `404` — Name outside the five published. **Example** ```sh curl -s https://staging.commsharbor.com/.well-known/api-catalog ``` ### `GET /apis.json` APIs.json (apisjson.org, 0.19): the index APIs.io harvests — the API, the MCP, OpenAPI, guide and OKF bundle in one file. Also at `/.well-known/apis.json`. - **URL:** `https://staging.commsharbor.com/apis.json` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** `application/json` in the APIs.json 0.19 format: `apis[]` with `baseURL`, `humanURL` and `properties[]`. **Example** ```sh curl -s https://staging.commsharbor.com/apis.json ``` ### `GET /api/` Discover the whole API: every endpoint, every auth mode and the MCP endpoint. - **URL:** `https://staging.commsharbor.com/api/` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** Structure: `ApiIndex`. - `name` (string) — Product name. - `description` (string) — What the product does, in one sentence. - `build` (string) — Deployed commit. - `environment` (string) — Which environment answered: `production` or `local`. - `base_url` (string) — Origin this API is served from. - `docs` (object) — Links to llms.txt, llms-full.txt, openapi.json, the MCP endpoint and the human UI. - `auth` (object) — Every authentication mode and how to obtain it. - `endpoints` (object[]) — Every endpoint with method, path, auth, absolute URL and what it returns. - `mcp` (object) — Remote MCP endpoint and transport. - `mcp_tools` (string[]) — Name of every MCP tool. ### `GET /api/health` Read liveness, environment and the commit currently deployed. Smoke tests wait for their own commit to appear here instead of racing edge propagation. - **URL:** `https://staging.commsharbor.com/api/health` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** Structure: `Health`. - `ok` (bool) — Always true when the Worker answers. - `app` (string) — Product name. - `build` (string) — Deployed commit; CI passes the short SHA at deploy time. - `environment` (string) — Which environment answered. - `timestamp` (string) — Response time (UTC, ISO-8601). ### `GET /mcp` Inspect the remote MCP server card: transport, protocol and tool count. `POST /mcp` speaks Streamable HTTP with JSON-RPC 2.0. The tools are the operations in this catalog; the MCP has no backend of its own. - **URL:** `https://staging.commsharbor.com/mcp` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `transport` (string) — How the server speaks — `streamable-http`. - `protocol_version` (string) — MCP protocol version the server implements. - `endpoint` (string) — Absolute URL to POST JSON-RPC to. - `server` (object) — `name` and `version` of this server; the version is the deployed commit. - `tools` (int) — How many tools the server exposes. - `usage` (string) — One line saying how to call it. - `api_index` (string) — The self-describing API index, for the operations behind the tools. ### `GET /api/pricing` Read monthly email packages and purchase entry points. - **URL:** `https://staging.commsharbor.com/api/pricing` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Query** - `lingua` (string) — Selected language. Without it, use the shared request language policy. Values: `en`, `pt`. **Response `200`** - `currency` (string) — Display currency: BRL only for Portuguese and country BR from the trusted origin. Otherwise USD, including unknown country. - `country` (string) — Country supplied by the trusted origin, or empty when unknown. A query or client header cannot set it. - `brl_per_usd` (number) — Configured reference exchange rate. This is not your card issuer's exchange rate. - `price_is_estimate` (bool) — True for USD display prices. Card charges use billing_currency and billing_price_cents. - `billing_currency` (string) — BRL. The current subscription provider charges Brazilian reais. - `interval` (string) — Monthly billing. - `auto_renew` (bool) — Monthly automatic renewal until cancellation. - `cancellation` (string) — Cancellation stops future charges. - `paid_access` (string) — Access lasts until the end of the paid period. - `trial_days` (int) — Zero. There is no automatic trial conversion. - `trial` (object) — Free receive-only trial for `days` (7) days, once per organization: storage_mb 1024 shared across unlimited mailboxes (mailboxes null), one domain, smtp_send false, no card and no automatic renewal (`expires` true). After it ends, writes without a paid plan answer 402 `email_trial_expired`. activation_ready is true only after native quota and protocol proof. Activation uses the organization trial route. A paid subscription enables sending only after backend confirmation. - `plans` (object[]) — Three packages with price_cents in display currency, billing_price_cents in BRL, domains, mailboxes, mailbox_gb, email_storage_gb, files_gb, aliases, features and on_demand. - `checkout_live` (bool) — Whether new real subscriptions are open. - `on_demand_activation` (string) — Agree scope and activation date before charging for on-demand services. - `quota` (PaymentQuota) — Public allowances and list prices: the free email check, the per-call email check and the mailbox packages (signed-in account only). Not personal usage. → see `PaymentQuota` under **Structures**. - `product` (string) — CommsHarbor. - `pricing` (string) — Current package catalog URL. - `billing` (string) — Monthly subscription offer catalog URL. - `api_index` (string) — API catalog URL. **Example** ```sh curl -s https://staging.commsharbor.com/api/pricing?lingua=en ``` ### `GET /api/billing` Read the same email package catalog at the billing address, with the subscription offers URL. - **URL:** `https://staging.commsharbor.com/api/billing` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Query** - `lingua` (string) — Selected language. Without it, use the shared request language policy. Values: `en`, `pt`. **Response `200`** - `currency` (string) — Display currency: BRL only for Portuguese and country BR from the trusted origin. Otherwise USD, including unknown country. - `country` (string) — Country supplied by the trusted origin, or empty when unknown. A query or client header cannot set it. - `brl_per_usd` (number) — Configured reference exchange rate. This is not your card issuer's exchange rate. - `price_is_estimate` (bool) — True for USD display prices. Card charges use billing_currency and billing_price_cents. - `billing_currency` (string) — BRL. The current subscription provider charges Brazilian reais. - `interval` (string) — Monthly billing. - `auto_renew` (bool) — Monthly automatic renewal until cancellation. - `cancellation` (string) — Cancellation stops future charges. - `paid_access` (string) — Access lasts until the end of the paid period. - `trial_days` (int) — Zero. There is no automatic trial conversion. - `trial` (object) — Free receive-only trial for `days` (7) days, once per organization: storage_mb 1024 shared across unlimited mailboxes (mailboxes null), one domain, smtp_send false, no card and no automatic renewal (`expires` true). After it ends, writes without a paid plan answer 402 `email_trial_expired`. activation_ready is true only after native quota and protocol proof. Activation uses the organization trial route. A paid subscription enables sending only after backend confirmation. - `plans` (object[]) — Three packages with price_cents in display currency, billing_price_cents in BRL, domains, mailboxes, mailbox_gb, email_storage_gb, files_gb, aliases, features and on_demand. - `checkout_live` (bool) — Whether new real subscriptions are open. - `on_demand_activation` (string) — Agree scope and activation date before charging for on-demand services. - `quota` (PaymentQuota) — Public allowances and list prices: the free email check, the per-call email check and the mailbox packages (signed-in account only). Not personal usage. → see `PaymentQuota` under **Structures**. - `product` (string) — CommsHarbor. - `pricing` (string) — Current package catalog URL. - `billing` (string) — Monthly subscription offer catalog URL. - `api_index` (string) — API catalog URL. **Example** ```sh curl -s https://staging.commsharbor.com/api/billing?lingua=en ``` ## Account ### `GET /api/auth/bootstrap` Prepare the browser for global sign-in. Sets a host-only HttpOnly browser cookie. CSRF is bound to the current session. No CORS. - **URL:** `https://staging.commsharbor.com/api/auth/bootstrap` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `csrf` (string) — X-CSRF-Token - `context` (string) — Opaque view context, also in X-MM-Context; not a credential / contexto opaco da vista, não é credencial. **Errors** - `400` — invalid_request - `403` — invalid_origin / invalid_csrf - `503` — auth_unavailable: a sessão anterior é preservada / the previous session is preserved ### `GET /api/account/profile` Read your global profile. Reads current preferences from the account. Edit them on your account page; products never own a separate profile. - **URL:** `https://staging.commsharbor.com/api/account/profile` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Response `200`** {profile:{name,locale,timeZone,theme,revision}} **Errors** - `401` — invalid_session - `503` — auth_unavailable **Example** ```js await fetch("https://staging.commsharbor.com/api/account/profile", {credentials: "same-origin"}).then(r => r.json()); ``` ### `GET /api/account/avatar` Read your global profile photo. Private WebP, up to 64 KiB, no cache. Change it on your account. No user ID or object URL accepted. - **URL:** `https://staging.commsharbor.com/api/account/avatar` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Response `200`** image/webp; Cache-Control: no-store **Errors** - `401` — invalid_session - `404` — not_found: no photo / sem foto - `503` — auth_unavailable **Example** ```js await fetch("https://staging.commsharbor.com/api/account/avatar", {credentials: "same-origin"}).then(r => {if (!r.ok) throw new Error("HTTP " + r.status); return r.blob();}); ``` ### `POST /api/auth/logout` Revoke this product session. Bootstrap/CSRF must belong to this browser and session. Other product sessions remain active. - **URL:** `https://staging.commsharbor.com/api/auth/logout` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Response `200`** - `ok` (bool) — true **Errors** - `400` — invalid_request - `403` — invalid_origin / invalid_csrf - `503` — auth_unavailable: a sessão anterior é preservada / the previous session is preserved **Example** ```js // Execute no console da página do produto / Run in the product page console. (async () => { const origin = "https://staging.commsharbor.com"; const {csrf} = await fetch(origin + "/api/auth/bootstrap").then(r => r.json()); const r = await fetch(origin + "/api/auth/logout", { method: "POST", credentials: "same-origin", headers: {"Content-Type": "application/json", "X-CSRF-Token": csrf}, body: JSON.stringify({}) }); if (!r.ok) throw new Error("Auth HTTP " + r.status); return r.json(); })(); ``` ### `GET /api/account/keys` List your API keys in this product. Never returns the key itself: name, last 4 characters, organization, creation, last use (hourly) and whether it still works. - **URL:** `https://staging.commsharbor.com/api/account/keys` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Response `200`** - `keys` (object[]) — `id`, `name`, `organizationId`, `last4`, `createdAt`, `lastUsedAt`, `revokedAt`, `active` (false when revoked or stopped by a password change / ending all sessions). **Errors** - `401` — invalid_session - `503` — auth_unavailable **Example** ```js await fetch("https://staging.commsharbor.com/api/account/keys", {credentials: "same-origin"}).then(r => r.json()); ``` ### `POST /api/account/keys/create` Create an API key for agents and scripts. Needs a sign-in within the last 2 hours; an organization key also needs a second factor in the session and the owner/admin role with this product enabled. At most 10 live keys per account and product. The key (`secret`) is returned ONCE. - **URL:** `https://staging.commsharbor.com/api/account/keys/create` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Body** (`application/json`) - `name` (string, required) — Up to 60 characters. - `organizationId` (string, required) — `null` for an account key. **Body example** ```json { "name": "agent", "organizationId": null } ``` **Response `200`** - `key` (object) — `id`, `name`, `organizationId`, `last4`, `createdAt`. - `secret` (string) — `mmk_…`, shown once. **Errors** - `400` — invalid_key_name / invalid_organization - `401` — invalid_session / reauth_required - `403` — invalid_origin / invalid_csrf / organization_forbidden / organization_mfa_required - `409` — key_limit_reached - `503` — auth_unavailable **Example** ```js (async () => { const {csrf} = await fetch("https://staging.commsharbor.com/api/auth/bootstrap").then(r => r.json()); const r = await fetch("https://staging.commsharbor.com/api/account/keys/create", {method: "POST", credentials: "same-origin", headers: {"Content-Type": "application/json", "X-CSRF-Token": csrf}, body: JSON.stringify({name: "agent", organizationId: null})}); return r.json(); })(); ``` ### `POST /api/account/keys/revoke` Revoke one of your API keys. Stops the key at once. Repeating is harmless. - **URL:** `https://staging.commsharbor.com/api/account/keys/revoke` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Body** (`application/json`) - `id` (string, required) — The key `id`. **Body example** ```json { "id": "…" } ``` **Response `200`** - `ok` (bool) — true **Errors** - `400` — invalid_key_id - `401` — invalid_session - `403` — invalid_origin / invalid_csrf - `404` — key_not_found - `503` — auth_unavailable **Example** ```js (async () => { const {csrf} = await fetch("https://staging.commsharbor.com/api/auth/bootstrap").then(r => r.json()); const r = await fetch("https://staging.commsharbor.com/api/account/keys/revoke", {method: "POST", credentials: "same-origin", headers: {"Content-Type": "application/json", "X-CSRF-Token": csrf}, body: JSON.stringify({id: "…"})}); return r.json(); })(); ``` ### `GET /api/account/apps` List the apps connected to your account in this product. The MCP clients you signed in with (OAuth), such as claude.ai or ChatGPT. Never returns a token. - **URL:** `https://staging.commsharbor.com/api/account/apps` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Response `200`** - `apps` (object[]) — Up to 50: `id`, `nome` (the app; its host when it identifies itself by a metadata document), `criadoEm`, `usadoEm` (hourly, or null). **Errors** - `401` — invalid_session - `503` — auth_unavailable **Example** ```js await fetch("https://staging.commsharbor.com/api/account/apps", {credentials: "same-origin"}).then(r => r.json()); ``` ### `POST /api/account/apps/revoke` Disconnect an app from your account. Stops the app's access at once; it asks you to sign in again. Repeating is harmless. - **URL:** `https://staging.commsharbor.com/api/account/apps/revoke` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Body** (`application/json`) - `id` (string, required) — The app `id`. **Body example** ```json { "id": "…" } ``` **Response `200`** - `ok` (bool) — true **Errors** - `400` — invalid_app_id - `401` — invalid_session - `403` — invalid_origin / invalid_csrf - `404` — app_not_found - `503` — auth_unavailable **Example** ```js (async () => { const {csrf} = await fetch("https://staging.commsharbor.com/api/auth/bootstrap").then(r => r.json()); const r = await fetch("https://staging.commsharbor.com/api/account/apps/revoke", {method: "POST", credentials: "same-origin", headers: {"Content-Type": "application/json", "X-CSRF-Token": csrf}, body: JSON.stringify({id: "…"})}); return r.json(); })(); ``` ### `GET /api/account/callouts` List the notices that you closed in this product. The keys of the notices that stay closed for your account, on every device, such as the explanation of an area. - **URL:** `https://staging.commsharbor.com/api/account/callouts` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Response `200`** - `callouts` (string[]) — Up to 200 keys, in alphabetical order. **Errors** - `401` — invalid_session - `403` — product_required - `503` — auth_unavailable **Example** ```js await fetch("https://staging.commsharbor.com/api/account/callouts", {credentials: "same-origin"}).then(r => r.json()); ``` ### `POST /api/account/callouts/dismiss` Close a notice for good. The notice does not open again for your account in this product. Repeating is harmless. - **URL:** `https://staging.commsharbor.com/api/account/callouts/dismiss` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Body** (`application/json`) - `key` (string, required) — The notice key: letters, digits and `_.:-`, up to 80. **Body example** ```json { "key": "financeiro_expense" } ``` **Response `200`** - `ok` (bool) — true **Errors** - `400` — invalid_callout - `401` — invalid_session - `403` — invalid_origin / invalid_csrf - `409` — too_many_callouts - `503` — auth_unavailable **Example** ```js (async () => { const {csrf} = await fetch("https://staging.commsharbor.com/api/auth/bootstrap").then(r => r.json()); const r = await fetch("https://staging.commsharbor.com/api/account/callouts/dismiss", {method: "POST", credentials: "same-origin", headers: {"Content-Type": "application/json", "X-CSRF-Token": csrf}, body: JSON.stringify({key: "financeiro_expense"})}); return r.json(); })(); ``` ### `POST /api/account/callouts/reopen` Open a closed notice again. Undoes the close: the notice shows again for your account in this product. A product also keeps an on/off choice here, as the hidden values of Finance. Repeating is harmless. - **URL:** `https://staging.commsharbor.com/api/account/callouts/reopen` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Body** (`application/json`) - `key` (string, required) — The notice key: letters, digits and `_.:-`, up to 80. **Body example** ```json { "key": "financeiro_expense" } ``` **Response `200`** - `ok` (bool) — true **Errors** - `400` — invalid_callout - `401` — invalid_session - `403` — invalid_origin / invalid_csrf - `503` — auth_unavailable **Example** ```js (async () => { const {csrf} = await fetch("https://staging.commsharbor.com/api/auth/bootstrap").then(r => r.json()); const r = await fetch("https://staging.commsharbor.com/api/account/callouts/reopen", {method: "POST", credentials: "same-origin", headers: {"Content-Type": "application/json", "X-CSRF-Token": csrf}, body: JSON.stringify({key: "financeiro_expense"})}); return r.json(); })(); ``` ### `POST /api/auth/wallet/agent/start` Start the wallet credential of an agent without an account. No account: the wallet proves it is hers by signing the message (EIP-4361). Signing does not pay or transfer anything. The message names this product and lasts 5 minutes. Before you sign, compare the message with the URL that you called. The domain on the first line must be the host of that URL. URI must be its origin. If one is different, do not sign. Sign it with personal_sign and send it to /api/auth/wallet/agent/token. - **URL:** `https://staging.commsharbor.com/api/auth/wallet/agent/start` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Body** (`application/json`) - `address` (string, required) — 0x…, a carteira (EOA ou contrato na Base) **Body example** ```json { "address": "0x2c7536E3605D9C16a7a3D7b1898e529396a65c23" } ``` **Response `200`** - `message` (string) — EIP-4361 - `issuedAt` (number) — segundos / seconds - `expiresIn` (number) — 300 **Errors** - `400` — invalid_wallet_address - `503` — auth_unavailable **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/auth/wallet/agent/start -H 'content-type: application/json' -d '{"address":"0x2c7536E3605D9C16a7a3D7b1898e529396a65c23"}' ``` ### `POST /api/auth/wallet/agent/token` Get the wallet credential (mmw_…) of this product. The wallet's signature of the start message, checked here (own key) or on Base (contract, EIP-1271/6492). The credential lasts 30 days: send `Authorization: Bearer mmw_…` to the routes that accept the wallet as owner (owner `x402:
`). Once the wallet is linked to an account, what it did here moves to the account when the person signs in. - **URL:** `https://staging.commsharbor.com/api/auth/wallet/agent/token` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Body** (`application/json`) - `address` (string, required) — 0x…, a mesma carteira do start / the same wallet as in start - `issuedAt` (number, required) — o issuedAt do start / start's issuedAt - `signature` (string, required) — personal_sign (0x…) **Body example** ```json { "address": "0x2c7536E3605D9C16a7a3D7b1898e529396a65c23", "issuedAt": 1791400000, "signature": "0x…" } ``` **Response `200`** - `token` (string) — mmw_… - `owner` (string) — x402:0x… - `expiresAt` (number) — segundos / seconds **Errors** - `400` — invalid_body - `401` — invalid_wallet - `429` — wallet_limited - `503` — wallet_unavailable / auth_unavailable **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/auth/wallet/agent/token -H 'content-type: application/json' -d '{"address":"0x2c7536E3605D9C16a7a3D7b1898e529396a65c23","issuedAt":1791400000,"signature":"0x…"}' ``` ### `POST /api/auth/claim/wallets` Move to the account what its wallets did without an account. The sign-in window calls it after every sign-in. For each wallet linked to the account: the rights bought here by x402 (owner x402:
) and what this product keeps for that owner. Repeating moves nothing. - **URL:** `https://staging.commsharbor.com/api/auth/claim/wallets` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Response `200`** - `carteiras` (number) — wallets - `direitos` (number) — rights moved **Errors** - `401` — invalid_session - `503` — auth_unavailable **Example** ```sh await MMConta.fetch(new URL("https://staging.commsharbor.com/api/auth/claim/wallets").pathname, { method: "POST", headers: { "content-type": "application/json" }, body: "{}" }) ``` ### `POST /api/guest` Open or restore a temporary workspace in this browser. Sets a host-only HttpOnly guest cookie. The SDK limits issuance to 20 per network per hour; a valid cookie is reused. - **URL:** `https://staging.commsharbor.com/api/guest` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `guest_token` (string) — Signed guest token for an API client. **Errors** - `429` — guest_rate_limited - `503` — auth_unavailable ### `GET /api/visitor` Read the temporary workspace id. The id is derived by the shared account library; product data stays under this id when you link an account. - **URL:** `https://staging.commsharbor.com/api/visitor` - **Auth:** `guest` — Temporary workspace of this browser (`POST /api/guest`): the HttpOnly `cm_guest` cookie, host-only, or the signed `cm_…` token in `X-Guest-Token` for an API client. It works without an account until `POST /api/auth/claim` attaches it to one; nothing signs anyone in automatically. **Response `200`** - `organization` (object) — `{id,name:null,role:'guest'}`. **Errors** - `401` — unauthorized / guest_ended - `503` — auth_unavailable **Example** ```js await fetch("https://staging.commsharbor.com/api/visitor", {credentials: "same-origin"}).then(r => r.json()); ``` ### `POST /api/auth/claim` Attach this browser's temporary workspace to your global account. Requires a recent sign-in with a second factor, as organization ownership does. The workspace stays available as a guest until the claim succeeds. - **URL:** `https://staging.commsharbor.com/api/auth/claim` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Response `200`** - `ok` (bool) — true when linked. **Errors** - `401` — unauthorized — no account session; sign in at `/conta/global` first - `409` — guest_claim_mfa_required / guest_already_claimed - `503` — auth_unavailable **Example** ```js await fetch("https://staging.commsharbor.com/api/auth/claim", {method: "POST", credentials: "same-origin", headers: {"content-type": "application/json", "x-csrf-token": csrf}, body: "{}"}).then(r => r.json()); ``` ### `GET /api/me` Read the global profile and the platform role, if any. `user.id` is the shared-account ID. Organizations are not listed here: they live in the shared account, which does not list them inside products yet — open a workspace by its ID with `GET /api/organizations/{organization_id}`. - **URL:** `https://staging.commsharbor.com/api/me` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Response `200`** - `user` (User) — The person behind the session. → see `User` under **Structures**. - `profile` (Profile) — Global MM profile — it belongs to the person, edited on the account, not to a tenant. → see `Profile` under **Structures**. - `platform_role` (string, may be null) — Platform role, when one was explicitly granted. Owning a tenant grants nothing here. **Errors** - `401` — No session, or the session expired. - `503` — auth_unavailable **Example** ```js await fetch("https://staging.commsharbor.com/api/me", {credentials: "same-origin"}).then(r => r.json()); ``` ## Installed app ### `POST /api/auth/pwa/install` Prepare a personal app installation. Requires recent sign-in, exact Origin and browser CSRF. Returns a private signed PIN and a no-store manifest address. At most 10 active installations per account and product. - **URL:** `https://staging.commsharbor.com/api/auth/pwa/install` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Body** (`application/json`) - `path` (string, required) — Same-origin task path, up to 1600 characters. - `state` (object, required) — Up to 30 allowlisted preference keys and string values. - `manifest` (object, required) — Public app name and same-origin icons. **Response `200`** {pin,path,manifest} **Errors** - `400` — invalid_installation_path / invalid_installation_state / invalid_installation_manifest - `401` — invalid_session / reauth_required - `409` — installation_not_created - `503` — auth_unavailable **Example** ```js (async () => { const {csrf} = await fetch("https://staging.commsharbor.com/api/auth/bootstrap").then(r => r.json()); const manifest = await fetch(document.querySelector('link[rel="manifest"]').href).then(r => r.json()); const r = await fetch("https://staging.commsharbor.com/api/auth/pwa/install", {method: "POST", credentials: "same-origin", headers: {"Content-Type": "application/json", "X-CSRF-Token": csrf}, body: JSON.stringify({path: location.pathname + location.search, state: {}, manifest})}); return r.json(); })(); ``` ### `POST /api/auth/pwa/restore` Restore an installed app. Requires the signed PIN, exact Origin and browser CSRF. Verifies host, product, account status, security version and installation revocation. Keeps the original authentication time. Sensitive actions still require recent sign-in. - **URL:** `https://staging.commsharbor.com/api/auth/pwa/restore` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Body** (`application/json`) - `pin` (string, required) — Private signed installation credential. **Response `200`** {ok:true,state,path,manifest}; HttpOnly session cookies **Errors** - `401` — invalid_installation - `403` — invalid_origin / invalid_csrf - `503` — auth_unavailable **Example** ```js (async () => { const {csrf} = await fetch("https://staging.commsharbor.com/api/auth/bootstrap").then(r => r.json()); const r = await fetch("https://staging.commsharbor.com/api/auth/pwa/restore", {method: "POST", credentials: "same-origin", headers: {"Content-Type": "application/json", "X-CSRF-Token": csrf}, body: JSON.stringify({pin: "…"})}); return r.json(); })(); ``` ### `GET /api/auth/pwa/manifest` Read the private installation manifest. Requires the installation cookie and its manifest key. Private, no-store. The start URL keeps the PIN in the fragment. - **URL:** `https://staging.commsharbor.com/api/auth/pwa/manifest` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Query** - `key` (string, required) — Key in the manifest address that the install or restore call returned. **Response `200`** application/manifest+json **Errors** - `401` — invalid_installation **Example** ```js await fetch("https://staging.commsharbor.com/api/auth/pwa/manifest?key=…", {credentials: "same-origin"}).then(r => r.json()) ``` ## Organizations ### `GET /api/account/organizations` List your organizations: ID, name and your role. Served by the shared account on this domain; every organization you belong to, whether or not this product is enabled there. Creating, renaming, members, invitations and organization API keys are on the account page, `/conta/global`. - **URL:** `https://staging.commsharbor.com/api/account/organizations` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Query** - `after` (string) — `next` of the previous page. **Response `200`** - `organizations` (object[]) — Up to 8 per page: `id`, `name`, `revision`, `role` (`owner`, `admin` or `member`) and `mfaRequired`. Product sessions also return `product: {id, enabled, revision}` for this product. Listing does not activate it. - `next` (string, may be null) — Cursor for the next page. **Errors** - `400` — invalid_organization_cursor - `401` — invalid_session - `404` — organization_not_found - `503` — auth_unavailable **Example** ```js await fetch("https://staging.commsharbor.com/api/account/organizations", {credentials: "same-origin"}).then(r => r.json()); ``` ### `GET /api/context` Resolve which organization and role the current session or API key is acting as. Read this before a write when you are not certain which tenant is active. Guessing is how data lands in the wrong organization. An organization API key answers `kind: api_key` with its scopes. - **URL:** `https://staging.commsharbor.com/api/context` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Headers** - `X-Organization-Id` (string, required) — Which organization to act in; required with a session. The shared account checks, on every request, that you belong to it and that CommsHarbor is enabled for it. An organization API key opens only its own organization: send that ID, or omit the header. **Response `200`** Structure: `Identity`. - `kind` (string) — How the identity was resolved. - `organizationId` (string) — The active organization. - `userId` (string) — The person's shared-account ID (session only). - `sessionId` (string) — Session identifier (session only). - `apiKeyId` (string) — The organization API key's ID (API key only). - `scopes` (string[]) — What the API key may do (API key only): the work permissions, never billing, erasure, exports or audit. - `role` (string, may be null) — Role inside that organization, from the shared account; null with an API key. - `organization` (object) — `{ id, name }` of the active organization; `name` is null with an API key. **Errors** - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `503` — The shared account is unavailable. **Example** ```sh curl -s https://staging.commsharbor.com/api/context -b "__Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" ``` ### `GET /api/organizations/:organization_id` Open one organization: its name, your role and its CommsHarbor plan. This is how a workspace is opened. Name and role come from the shared account (null with an organization API key, which carries neither); the plan is the organization's global entitlement in CommsHarbor. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Active organization ID (the organization's id in the shared account). It must match `X-Organization-Id`. **Headers** - `X-Organization-Id` (string, required) — Which organization to act in; required with a session. The shared account checks, on every request, that you belong to it and that CommsHarbor is enabled for it. An organization API key opens only its own organization: send that ID, or omit the header. **Response `200`** Structure: `Organization`. - `id` (string) — Organization ID in the shared account, used in every tenant route. - `name` (string, may be null) — Display name, from the shared account; null with an organization API key. - `role` (string, may be null) — Your role in it, from the shared account; null with an organization API key. - `email_workspace` (string) — Tenant-scoped email workspace URL. Read it for the current plan, allowances and resources. **Errors** - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `503` — The shared account is unavailable. **Example** ```sh curl -s https://staging.commsharbor.com/api/organizations/$ORG -b "__Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" ``` ## Credentials ### `GET /api/organizations/:organization_id/audit` List the append-only audit trail of the organization. Audit records are never rewritten and never carry recipient PII. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/audit` - **Auth:** `organization_admin` — Owner or admin of the organization (shared-account roles), signed in with a second factor. Never an API key. **Path parameters** - `organization_id` (string, required) — Active organization ID (the organization's id in the shared account). It must match `X-Organization-Id`. **Query** - `cursor` (string) — Opaque cursor from the previous page. Do not build or parse it. - `limit` (int) — Page size, from 1 to 100. Default: `50`. **Response `200`** Structure: `PageCamel`. - `items` (AuditEvent[]) — The records on this page. → see `AuditEvent` under **Structures**. - `nextCursor` (string, may be null) — Cursor for the next page; null when there are no more. **Errors** - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `503` — The shared account is unavailable. **Example** ```sh curl -s 'https://staging.commsharbor.com/api/organizations/$ORG/audit?limit=20' -b "__Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" ``` ### `GET /api/platform/context` Confirm an explicitly granted platform administrator. Tenant ownership grants nothing here: platform access is a separate, explicit grant. - **URL:** `https://staging.commsharbor.com/api/platform/context` - **Auth:** `platform_admin` — Session with an explicit platform_roles grant. Tenant ownership does not grant platform access. **Response `200`** - `role` (string) — The platform role that was granted. - `user_id` (string) — Who holds it. **Errors** - `401` — No session. - `403` — This person has no platform grant. **Example** ```sh curl -s https://staging.commsharbor.com/api/platform/context -b "__Host-mm-auth=$SESSION" ``` ## Email setup ### `GET /api/organizations/:organization_id/email/domain-import/:service` Read authorized Google metadata. This does not prove DNS ownership. Requires an account session in this organization. Reads site metadata only. Google access and refresh tokens remain encrypted on the server. This does not change DNS, buy a subscription or grant another product access to Google data. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/domain-import/:service` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID. Must match X-Organization-Id. - `service` (string, required) — search_console or analytics. Each connection has its own consent. **Response `200`** - `connected` (bool) — This identity has a saved connection for this product and service. - `domains` (object[]) — Distinct domain names from authorized properties or selected Analytics web streams. - `groups` (object[], optional) — Analytics accounts and properties. No reports are read. - `resolved` (bool, optional) — Selected Analytics properties have been resolved to domains. - `available` (bool, optional) — Google client configuration is available. This does not assert consent or verification approval. **Errors** - `401` — Account session required. Organization keys cannot access personal Google connections. - `403` — Write requires an owner or admin, the same Origin and valid CSRF. - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Google connection required or changed. - `503` — Google import unavailable. Retry or use account/manual domain registration. **Example** ```sh curl -s https://staging.commsharbor.com/api/organizations/$ORG/email/domain-import/search_console -b "__Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" ``` ### `POST /api/organizations/:organization_id/email/domain-import/:service/connect` Start five-minute Google consent with PKCE. Return an authorization URL. Signing in does not grant this access. Requires an account session in this organization. Reads site metadata only. Google access and refresh tokens remain encrypted on the server. This does not change DNS, buy a subscription or grant another product access to Google data. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/domain-import/:service/connect` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID. Must match X-Organization-Id. - `service` (string, required) — search_console or analytics. Each connection has its own consent. **Body** (`application/json`) - `language` (string) — Consent return language. Values: `en`, `pt`. **Response `200`** - `redirect` (string) — Google consent URL. The owner must approve it in a browser. **Errors** - `401` — Account session required. Organization keys cannot access personal Google connections. - `403` — Write requires an owner or admin, the same Origin and valid CSRF. - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Google connection required or changed. - `503` — Google import unavailable. Retry or use account/manual domain registration. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/domain-import/search_console/connect -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H 'content-type: application/json' -d '{"language":"en"}' ``` ### `POST /api/organizations/:organization_id/email/domain-import/:service/resolve` Resolve website addresses for up to 20 selected Analytics properties. Search Console does not use this route. Requires an account session in this organization. Reads site metadata only. Google access and refresh tokens remain encrypted on the server. This does not change DNS, buy a subscription or grant another product access to Google data. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/domain-import/:service/resolve` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID. Must match X-Organization-Id. - `service` (string, required) — search_console or analytics. Each connection has its own consent. **Body** (`application/json`) - `properties` (array, required) — Authorized properties/ID values from the catalog, at most 20 unique entries. **Response `200`** - `connected` (bool) — This identity has a saved connection for this product and service. - `domains` (object[]) — Distinct domain names from authorized properties or selected Analytics web streams. - `groups` (object[], optional) — Analytics accounts and properties. No reports are read. - `resolved` (bool, optional) — Selected Analytics properties have been resolved to domains. - `available` (bool, optional) — Google client configuration is available. This does not assert consent or verification approval. **Errors** - `401` — Account session required. Organization keys cannot access personal Google connections. - `403` — Write requires an owner or admin, the same Origin and valid CSRF. - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Google connection required or changed. - `503` — Google import unavailable. Retry or use account/manual domain registration. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/domain-import/analytics/resolve -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H 'content-type: application/json' -d '{"properties":["properties/123456789"]}' ``` ### `POST /api/organizations/:organization_id/email/domain-import/:service/disconnect` Remove this product's saved Google connection and pending consent. Existing email and service resources remain intact. Requires an account session in this organization. Reads site metadata only. Google access and refresh tokens remain encrypted on the server. This does not change DNS, buy a subscription or grant another product access to Google data. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/domain-import/:service/disconnect` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID. Must match X-Organization-Id. - `service` (string, required) — search_console or analytics. Each connection has its own consent. **Response `200`** - `connected` (bool) — This identity has a saved connection for this product and service. - `domains` (object[]) — Distinct domain names from authorized properties or selected Analytics web streams. - `groups` (object[], optional) — Analytics accounts and properties. No reports are read. - `resolved` (bool, optional) — Selected Analytics properties have been resolved to domains. - `available` (bool, optional) — Google client configuration is available. This does not assert consent or verification approval. **Errors** - `401` — Account session required. Organization keys cannot access personal Google connections. - `403` — Write requires an owner or admin, the same Origin and valid CSRF. - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Google connection required or changed. - `503` — Google import unavailable. Retry or use account/manual domain registration. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/domain-import/search_console/disconnect -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H 'content-type: application/json' -d '{}' ``` ### `GET /api/organizations/:organization_id/email/domains/:resource_id/products` Read services associated with this exact domain. The private email backend confirms domain ownership in this organization. Selected native products must already be enabled. Association is idempotent. It does not create a PageAudit project, HookPulse monitor or paid subscription. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/domains/:resource_id/products` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID. Must match X-Organization-Id. - `resource_id` (string, required) — Domain ID in the caller's email organization. **Response `200`** - `services` (string[]) — Associated services with native organization access still enabled. **Errors** - `400` — Invalid or duplicate service. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Native product access must be enabled first. - `503` — Domain services unavailable. **Example** ```sh curl -s https://staging.commsharbor.com/api/organizations/$ORG/email/domains/$DOMAIN/products -b "__Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" ``` ### `POST /api/organizations/:organization_id/email/domains/:resource_id/products` Associate explicitly selected services with this domain. The private email backend confirms domain ownership in this organization. Selected native products must already be enabled. Association is idempotent. It does not create a PageAudit project, HookPulse monitor or paid subscription. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/domains/:resource_id/products` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID. Must match X-Organization-Id. - `resource_id` (string, required) — Domain ID in the caller's email organization. **Body** (`application/json`) - `services` (array, required) — At most two unique values: pageaudit and hookpulse. **Response `200`** - `services` (string[]) — Associated services with native organization access still enabled. **Errors** - `400` — Invalid or duplicate service. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Native product access must be enabled first. - `503` — Domain services unavailable. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/domains/$DOMAIN/products -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H 'content-type: application/json' -d '{"services":["pageaudit"]}' ``` ## Realtime ### `POST /api/realtime/ticket` Create a short-lived browser ticket for the selected email workspace. Use the shared browser client with the session, CSRF and X-Organization-Id headers. Guests and API keys cannot create browser tickets. Server integrations use the HTTP management API. - **URL:** `https://staging.commsharbor.com/api/realtime/ticket` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Response `200`** - `ticket` (string) — Opaque browser credential. Do not log or store it. - `expires_in` (int) — Seconds before an unused ticket expires. - `namespace` (string) — Product namespace on the shared transport. **Errors** - `401` — Session ended. - `403` — Organization access denied. - `503` — Live channel unavailable. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/realtime/ticket -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H 'content-type: application/json' -d '{}' ``` ### `GET /api/email/workspaces/:id` Read the aggregate used by the live email workspace. The ID must match X-Organization-Id. Membership is checked again for each snapshot and delivered event. Events contain only an opaque change ID. DNS checks run in the private backend, with a 24-hour deadline and a visible resume action after pause. - **URL:** `https://staging.commsharbor.com/api/email/workspaces/:id` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `id` (string, required) — Selected organization ID. **Response `200`** - `plan` (string, may be null) — Current free, paid or operator bootstrap plan. - `subscription` (object) — Observed service state and valid_until. Optional payment has state confirmed, plan, environment, valid_until and renewal_state from the current paid grant. A sandbox payment cannot activate a production service. Cancellation stops renewal and preserves the confirmed paid period. No payer or card data. - `capabilities` (object) — Observed smtp_send, storage_mode and storage_mb. Trial uses shared storage and denies sending. A paid upgrade can remain awaiting_activation while native mailbox policy is updated. - `bootstrap` (bool) — Operator-managed adoption. - `activation_required` (bool, optional) — The confirmed payment environment cannot provision this control environment. Request operator activation. This field does not grant provisioning. - `access_state` (string) — Active or expired paid access. Expiry preserves stored mailbox data. - `usage` (object) — Reserved domain, mailbox, alias and storage counts. - `domains` (object[]) — Domains with observed state, DNS provider, copyable setup instructions and verified webmail URLs. dns_progress has completed, total, percent, ready, checked_at and records. Each record has verified, status (pending: no answer of this type; mismatch: different published value; unavailable: lookup failed; verified: matched) and observed (up to 16 published values, 4096 characters each). No observation means not checked yet. dns_monitor has state and, when scheduled, next_check_at in UTC; checking is true while the job runs. A due time is not a propagation estimate. Percent counts confirmed records, not delivery readiness. DNS completion alone does not grant mailbox creation. Assistance has job_id, state and requested_at. - `mailboxes` (object[]) — Mailbox addresses, display names and quotas. No passwords. - `aliases` (object[]) — Alias addresses and destinations. - `jobs` (object[]) — At most 20 recent jobs. Monitoring is an active scheduled observation, not a completed setup. Each job also has its direct status_url. **Errors** - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `503` — The shared account is unavailable. **Example** ```sh curl -s https://staging.commsharbor.com/api/email/workspaces/$ORG -b "__Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" ``` ## Email ### `GET /api/email/plans` Read the free Trial, three paid packages, storage allowances and activation terms. - **URL:** `https://staging.commsharbor.com/api/email/plans` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Query** - `lingua` (string) — Selected language. Without it, use the shared request language policy. Values: `en`, `pt`. **Response `200`** - `currency` (string) — Display currency: BRL only for Portuguese and country BR from the trusted origin. Otherwise USD, including unknown country. - `country` (string) — Country supplied by the trusted origin, or empty when unknown. A query or client header cannot set it. - `brl_per_usd` (number) — Configured reference exchange rate. This is not your card issuer's exchange rate. - `price_is_estimate` (bool) — True for USD display prices. Card charges use billing_currency and billing_price_cents. - `billing_currency` (string) — BRL. The current subscription provider charges Brazilian reais. - `interval` (string) — Monthly billing. - `auto_renew` (bool) — Monthly automatic renewal until cancellation. - `cancellation` (string) — Cancellation stops future charges. - `paid_access` (string) — Access lasts until the end of the paid period. - `trial_days` (int) — Zero. There is no automatic trial conversion. - `trial` (object) — Free receive-only trial for `days` (7) days, once per organization: storage_mb 1024 shared across unlimited mailboxes (mailboxes null), one domain, smtp_send false, no card and no automatic renewal (`expires` true). After it ends, writes without a paid plan answer 402 `email_trial_expired`. activation_ready is true only after native quota and protocol proof. Activation uses the organization trial route. A paid subscription enables sending only after backend confirmation. - `plans` (object[]) — Three packages with price_cents in display currency, billing_price_cents in BRL, domains, mailboxes, mailbox_gb, email_storage_gb, files_gb, aliases, features and on_demand. - `checkout_live` (bool) — Whether new real subscriptions are open. - `on_demand_activation` (string) — Agree scope and activation date before charging for on-demand services. **Example** ```sh curl -s https://staging.commsharbor.com/api/email/plans?lingua=en ``` ### `GET /api/organizations/:organization_id/email` Read the email workspace. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. **Prepared results and when to use them** We operate the mail server and webmail. Your agent manages the authorized domains and mailboxes through the existing service. Read /api/email/plans. If trial.activation_ready is true, activate the 7-day trial, verify your domain and create mailboxes. They share 1 GB and can receive through webmail or IMAP. No card or automatic conversion. A monthly package buys sending and the listed mailbox and storage capacity. Sending stays disabled during the trial, including SMTP and external filter forwarding. The human account accepts renewal and cancellation; an organization key manages service but cannot buy it. Check checkout_live, domain readiness and observed sending capability. A payment or accepted job alone does not prove activation or delivery. Enterprise services can require activation on demand. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. **Response `200`** - `plan` (string, may be null) — Current free, paid or operator bootstrap plan. - `subscription` (object) — Observed service state and valid_until. Optional payment has state confirmed, plan, environment, valid_until and renewal_state from the current paid grant. A sandbox payment cannot activate a production service. Cancellation stops renewal and preserves the confirmed paid period. No payer or card data. - `capabilities` (object) — Observed smtp_send, storage_mode and storage_mb. Trial uses shared storage and denies sending. A paid upgrade can remain awaiting_activation while native mailbox policy is updated. - `bootstrap` (bool) — Operator-managed adoption. - `activation_required` (bool, optional) — The confirmed payment environment cannot provision this control environment. Request operator activation. This field does not grant provisioning. - `access_state` (string) — Active or expired paid access. Expiry preserves stored mailbox data. - `usage` (object) — Reserved domain, mailbox, alias and storage counts. - `domains` (object[]) — Domains with observed state, DNS provider, copyable setup instructions and verified webmail URLs. dns_progress has completed, total, percent, ready, checked_at and records. Each record has verified, status (pending: no answer of this type; mismatch: different published value; unavailable: lookup failed; verified: matched) and observed (up to 16 published values, 4096 characters each). No observation means not checked yet. dns_monitor has state and, when scheduled, next_check_at in UTC; checking is true while the job runs. A due time is not a propagation estimate. Percent counts confirmed records, not delivery readiness. DNS completion alone does not grant mailbox creation. Assistance has job_id, state and requested_at. - `mailboxes` (object[]) — Mailbox addresses, display names and quotas. No passwords. - `aliases` (object[]) — Alias addresses and destinations. - `jobs` (object[]) — At most 20 recent jobs. Monitoring is an active scheduled observation, not a completed setup. Each job also has its direct status_url. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s https://staging.commsharbor.com/api/organizations/$ORG/email -b "__Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" ``` ### `POST /api/organizations/:organization_id/email/trial` Start the free receive-only Trial for 7 days, once per organization: 1 GB shared storage, unlimited mailboxes and no outgoing SMTP or external filter forwarding. No card, renewal or charge. After 7 days, writes without a paid plan answer 402 `email_trial_expired`. Requires a new workspace and operator-proved native quota. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/trial` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/trial -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{}' ``` ### `GET /api/organizations/:organization_id/email/domain-setup` Find an existing domain. Use it before a purchase. Return its organization and domain IDs only when this exact caller can open that organization. Otherwise return existing: null. This read creates no charge or job. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/domain-setup` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. **Query** - `domain` (string, required) — Domain to check, at most 253 characters. **Response `200`** - `existing` (object, may be null) — Authorized existing domain: organization_id, domain_id and organization name. Null also covers a foreign or unavailable organization; no foreign ownership information is returned. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s https://staging.commsharbor.com/api/organizations/$ORG/email/domain-setup?domain=example.com -b "__Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" ``` ### `POST /api/organizations/:organization_id/email/domains` Register a domain and its ownership challenge. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/domains` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Body** (`application/json`) - `domain` (string, required) — Exact domain name. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/domains -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{"domain":"example.com"}' ``` ### `GET /api/organizations/:organization_id/email/domains/:resource_id` Read domain setup, DNS records and observed readiness. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/domains/:resource_id` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. - `resource_id` (string, required) — Opaque resource ID returned by this email API. **Response `200`** - `domain` (object) — Domain setup and observed readiness. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s https://staging.commsharbor.com/api/organizations/$ORG/email/domains/$DOMAIN -b "__Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" ``` ### `POST /api/organizations/:organization_id/email/domains/:resource_id/verify` Queue a check of ownership, DNS and certificates. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/domains/:resource_id/verify` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. - `resource_id` (string, required) — Opaque resource ID returned by this email API. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/domains/$DOMAIN/verify -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{}' ``` ### `POST /api/organizations/:organization_id/email/domains/:resource_id/assistance` Request assisted DNS setup. The durable request waits for operator activation. It does not change DNS or expose a provider credential. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/domains/:resource_id/assistance` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. - `resource_id` (string, required) — Opaque resource ID returned by this email API. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/domains/$DOMAIN/assistance -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{}' ``` ### `POST /api/organizations/:organization_id/email/mailboxes` Create a mailbox within the current allowance. Trial mailboxes share 1 GB and cannot send email. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/mailboxes` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Body** (`application/json`) - `domain_id` (string, required) — Domain ID from the workspace. - `local_part` (string, required) — Mailbox name before @. - `name` (string, required) — Mailbox display name. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/mailboxes -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{"domain_id":"$DOMAIN","local_part":"ana","name":"Ana Souza"}' ``` ### `PATCH /api/organizations/:organization_id/email/mailboxes/:resource_id` Change mailbox name or quota within the plan. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/mailboxes/:resource_id` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. - `resource_id` (string, required) — Opaque resource ID returned by this email API. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Body** (`application/json`) - `name` (string) — Display name. - `quota_mb` (int) — Quota in MiB. Must fit the plan and current usage. - `files_quota_mb` (int) — File allowance in MiB. The sum of mailbox allowances must fit files_gb in the plan. Zero disables files. Existing files are preserved. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPATCH https://staging.commsharbor.com/api/organizations/$ORG/email/mailboxes/$MAILBOX -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{"name":"Ana Souza","quota_mb":2048}' ``` ### `POST /api/organizations/:organization_id/email/mailboxes/:resource_id/password` Set the mailbox password. It is encrypted for the executor and is never returned. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/mailboxes/:resource_id/password` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. - `resource_id` (string, required) — Opaque resource ID returned by this email API. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Body** (`application/json`) - `password` (string, required) — New mailbox password: 14 to 128 characters, with no control characters. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/mailboxes/$MAILBOX/password -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{"password":"$MAILBOX_PASSWORD"}' ``` ### `POST /api/organizations/:organization_id/email/mailboxes/:resource_id/suspend` Suspend access while preserving mailbox data. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/mailboxes/:resource_id/suspend` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. - `resource_id` (string, required) — Opaque resource ID returned by this email API. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/mailboxes/$MAILBOX/suspend -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{}' ``` ### `POST /api/organizations/:organization_id/email/mailboxes/:resource_id/resume` Restore suspended mailbox access. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/mailboxes/:resource_id/resume` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. - `resource_id` (string, required) — Opaque resource ID returned by this email API. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/mailboxes/$MAILBOX/resume -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{}' ``` ### `POST /api/organizations/:organization_id/email/aliases` Create an alias to existing mailboxes in this organization. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/aliases` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Body** (`application/json`) - `domain_id` (string, required) — Domain ID from the workspace, where the alias is created. - `local_part` (string, required) — Alias name before @. - `destinations` (array, required) — Existing mailbox addresses in this organization. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/aliases -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{"domain_id":"$DOMAIN","local_part":"sales","destinations":["ana@example.com"]}' ``` ### `PATCH /api/organizations/:organization_id/email/aliases/:resource_id` Change the alias destinations within this organization. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/aliases/:resource_id` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. - `resource_id` (string, required) — Opaque resource ID returned by this email API. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Body** (`application/json`) - `destinations` (array, required) — Existing mailbox addresses. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPATCH https://staging.commsharbor.com/api/organizations/$ORG/email/aliases/$ALIAS -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{"destinations":["ana@example.com","bruno@example.com"]}' ``` ### `POST /api/organizations/:organization_id/email/aliases/:resource_id/suspend` Suspend an alias without deleting its configuration. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/aliases/:resource_id/suspend` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. - `resource_id` (string, required) — Opaque resource ID returned by this email API. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/aliases/$ALIAS/suspend -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{}' ``` ### `POST /api/organizations/:organization_id/email/aliases/:resource_id/resume` Restore a suspended alias without changing its destinations. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/aliases/:resource_id/resume` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. - `resource_id` (string, required) — Opaque resource ID returned by this email API. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/aliases/$ALIAS/resume -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{}' ``` ### `GET /api/organizations/:organization_id/email/jobs/:resource_id` Read one durable job in this organization. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/jobs/:resource_id` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. - `resource_id` (string, required) — Opaque resource ID returned by this email API. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s https://staging.commsharbor.com/api/organizations/$ORG/email/jobs/$JOB -b "__Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" ``` ### `POST /api/organizations/:organization_id/email/services` Request an included service with activation on demand. No guest access. Members can read. Owners, admins and organization keys can manage email. The private service credential stays on the server. Mailbox passwords and message content are never returned. - **URL:** `https://staging.commsharbor.com/api/organizations/:organization_id/email/services` - **Auth:** `organization` — Shared account session plus `X-Organization-Id`: the shared account checks, on every request, the membership, the role and that CommsHarbor is enabled for the organization; owners and admins need a second factor. Agents can use an organization API key instead: an owner or admin creates it on the account page (`/conta/global`) and it goes as `Authorization: Bearer mmk_…` or `X-Api-Key`. It opens only its own organization, works while its creator is still an owner or admin there, and manages domains, mailboxes and aliases — never billing, erasure, exports or the audit trail. **Path parameters** - `organization_id` (string, required) — Organization ID from the shared account. It must match X-Organization-Id. **Headers** - `Idempotency-Key` (string, required) — Stable key of 8 to 128 characters. Reuse it only with the same operation and body. **Body** (`application/json`) - `service` (string, required) — Service code from the plan catalog. Values: `migration`, `chat`, `meetings`, `documents`, `shared_mailboxes`, `bookings`, `scheduled_send`, `signatures`. **Response `200`** - `job` (object) — Durable job ID, status and status_url. A 202 response is acceptance, not completion. **Errors** - `400` — Invalid fields or missing idempotency key. - `401` — No signed-in session, or the API key is invalid or revoked (`invalid_api_key`); an old `ch_…` key answers `api_key_retired`. - `403` — The session or key lacks the permission this operation needs (an API key never reaches billing, erasure, exports or the audit trail), an account key was used where an organization key is needed (`organization_key_required`), or an owner/admin has no second factor (`organization_mfa_required`). - `404` — The organization is not available to this session or key (no membership, CommsHarbor is not enabled for it, or the key belongs to another organization), or the resource does not exist in it. Another tenant's ID answers the same 404 — the API never confirms that it exists elsewhere. - `409` — Conflicting replay, pending setup or plan not active. - `429` — Daily provisioning capacity reached. Retry later with the same idempotency key. - `503` — Private email backend unavailable or Trial activation has not passed native proof. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/organizations/$ORG/email/services -b "__Host-mm-auth-browser=$BROWSER; __Host-mm-auth=$SESSION" -H "X-Organization-Id: $ORG" -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "Idempotency-Key: $KEY" -H 'content-type: application/json' -d '{"service":"migration"}' ``` ## Email security check ### `GET /api/email-check` Check SPF, DKIM, DMARC, MX, MTA-STS and BIMI of a domain, with a 0-100 score and what to fix. Public DNS only, no account and no charge. The same domain is served from memory for 10 minutes. A network can run 30 new checks per day. DKIM is looked up in common selectors only; `dkim_not_found` does not prove that no key exists. `incomplete: true` means a DNS answer failed and the score can be lower than the real one; `unread` names those parts, and a failed query never becomes a missing finding. - **URL:** `https://staging.commsharbor.com/api/email-check` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Query** - `domain` (string, required) — Public domain to check, such as example.com. A subdomain or URL is reduced to its registrable domain. **Response `200`** - `domain` (string) — Registrable domain that was checked. - `score` (int) — 0 to 100: DMARC up to 40, SPF 20, DKIM 20, MX 10, MTA-STS 5 and BIMI 5. - `rating` (string) — protected (90+), good (70+), at_risk (40+) or exposed. - `findings` (object[]) — `{code, severity}`, most severe first. Codes: dmarc_missing, dmarc_none, spf_plus_all, spf_missing, spf_multiple, dmarc_quarantine, dkim_not_found, spf_neutral, spf_softfail, dmarc_no_reports, mx_missing, mta_sts_missing, bimi_missing. - `spf` (object) — `{record, ending, multiple}`: the first SPF record, its `all` ending and whether there are two. - `dmarc` (object) — `{record, policy, reports}`: policy reject, quarantine, none or null; reports when `rua` is set. - `dkim` (object) — `{found, checked}`: selectors with a published key and the selectors looked up. - `mx` (string[]) — MX records as `priority host`. - `mta_sts` (bool) — An MTA-STS policy record exists. - `bimi` (bool) — A BIMI record exists at the default selector. - `unread` (string[]) — Parts whose DNS query failed (spf, dmarc, dkim, mx, mta_sts, bimi). They have no findings and no points. - `incomplete` (bool) — At least one DNS query failed. - `checked_at` (string) — ISO time of the DNS reading. - `share_url` (string) — Public page with this result. - `badge_url` (string) — SVG badge with the score. **Errors** - `400` — domain_invalid: not a public domain. - `429` — rate_limited: 30 new checks per account, or per network without an account, per day. - `503` — dns_unavailable: the DNS lookup failed; limit_unavailable: the daily limit could not be checked. Retry in a minute. **Example** ```sh curl -s "https://staging.commsharbor.com/api/email-check?domain=example.com" ``` ### `GET /api/email-check/badge` SVG badge with the email security score of a domain, for a website or README. Public DNS only, no account and no charge. The same domain is served from memory for 10 minutes. A network can run 30 new checks per day. The badge does not use the network's daily checks. An invalid domain or a failed lookup shows "unknown". - **URL:** `https://staging.commsharbor.com/api/email-check/badge` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Query** - `domain` (string, required) — Public domain to check, such as example.com. A subdomain or URL is reduced to its registrable domain. **Response `200`** `image/svg+xml` — a 20px-high badge with the score in the colour of its rating. **Example** ```sh curl -s "https://staging.commsharbor.com/api/email-check/badge?domain=example.com" ``` ### `GET /api/x402/email-check` Checks the email security of a domain for an agent, paid per call: SPF, DKIM, DMARC, MX and a score, with no account. The check of `GET /api/email-check`, sold per call to agents, with no account and without the 30 free checks per day before. A request without payment gets the 402 with the price; a paid one gets the audit in the same response, with the payment in `cobranca`. DKIM is looked up in common selectors only; `incomplete: true` means a DNS answer failed. A refused domain, the hourly limit of the service and a failed DNS lookup are not charged. **Prepared results and when to use them** DNS lookups, record parsing and assembling the domain's email-policy findings. GET /api/email-check offers the same check within its free allowance. Use it first when it covers your task. The x402 route buys a check from the first call, without an account or the free allowance first. Monthly domain-email packages buy mailboxes and storage, not this check; management requires organization authority. DKIM checks common selectors only. Inspect incomplete and unread. A score does not prove inbox placement, stop every phishing attack or verify the contents of a mailbox. - **URL:** `https://staging.commsharbor.com/api/x402/email-check` - **Auth:** `credito` — Credit token in `Authorization: Bearer cred_…` or `X-Credito`. For recovered x402 funds, use the wallet credential mmw_… in Bearer or X-Wallet-Token, issued through /api/auth/wallet/agent/start and /api/auth/wallet/agent/token. **Query** - `domain` (string, required) — Public domain to check, such as example.com. A subdomain or URL is reduced to its registrable domain. e.g.: `example.com`. **Headers** - `authorization` (string) — `Bearer mmk_…` (API key) or `Bearer mmo_…` (OAuth): the paid call uses the account balance without another header. Without an account, use prepaid credit from `POST /api/credito` as `Bearer cred_…`. - `x-api-key` (string) — The mmk_… API key for this product. It identifies the account and authorizes its balance for the paid call. - `payment-signature` (string) — The signed x402 payment proof (base64): `PAYMENT-SIGNATURE` (v2) or `X-PAYMENT` (v1). - `x-wallet-token` (string) — To recover an x402 response within 24 hours, repeat the same request and payment proof. Send the payer wallet's `mmw_…` credential here, issued through `/api/auth/wallet/agent/start` and `/api/auth/wallet/agent/token`. There is no new charge. **Response `200`** Structure: `VerificacaoAvulsa`. - `domain` (string) — Registrable domain that was checked. - `score` (int) — 0 to 100: DMARC up to 40, SPF 20, DKIM 20, MX 10, MTA-STS 5 and BIMI 5. - `rating` (string) — protected (90+), good (70+), at_risk (40+) or exposed. - `findings` (object[]) — `{code, severity}`, most severe first. Codes: dmarc_missing, dmarc_none, spf_plus_all, spf_missing, spf_multiple, dmarc_quarantine, dkim_not_found, spf_neutral, spf_softfail, dmarc_no_reports, mx_missing, mta_sts_missing, bimi_missing. - `spf` (object) — `{record, ending, multiple}`: the first SPF record, its `all` ending and whether there are two. - `dmarc` (object) — `{record, policy, reports}`: policy reject, quarantine, none or null; reports when `rua` is set. - `dkim` (object) — `{found, checked}`: selectors with a published key and the selectors looked up. - `mx` (string[]) — MX records as `priority host`. - `mta_sts` (bool) — An MTA-STS policy record exists. - `bimi` (bool) — A BIMI record exists at the default selector. - `unread` (string[]) — Parts whose DNS query failed (spf, dmarc, dkim, mx, mta_sts, bimi). They have no findings and no points. - `incomplete` (bool) — At least one DNS query failed. - `checked_at` (string) — ISO time of the DNS reading. - `share_url` (string) — Public page with this result. - `badge_url` (string) — SVG badge with the score. - `cobranca` (CobrancaDaChamada) — How this call was paid. → see `CobrancaDaChamada` under **Structures**. **Errors** - `400` — Paid without `domain` (`missing_input`) or with a domain that is not public (`domain_invalid`), both with `example`. Not charged. - `401` — API key refused (`invalid_api_key`), OAuth token refused (`invalid_token`), credit refused (`credito_invalido`), test credit outside dev (`credito_simulado`), or recovery without wallet authentication (`wallet_proof_required`). The first x402 purchase needs no account. - `402` — No payment: `accepts` (x402, USDC on Base) with the price of this call, at least US$ 0.01; `credito.preco_desta_chamada`, the lower price with prepaid credit; and `pacotes` (the credit top-ups and how many calls each one pays). Credit without balance answers `saldo_insuficiente`. - `409` — Payment is in progress, the request differs from the original, or the amount was recovered as balance. Do not sign another authorization to retry the purchase. - `410` — The 24-hour response recovery period ended. The financial record remains; the same proof cannot cause another charge. - `429` — rate_limited: the hourly limit of the service. Retry after the stated delay. Not charged. - `503` — dns_unavailable: the DNS lookup failed. Retry in a minute. Not charged. **Example** ```sh curl -s -i 'https://staging.commsharbor.com/api/x402/email-check?domain=example.com' ``` ### `GET /api/email-raio-x` The monthly Brazil email security report: DMARC and SPF totals of city halls, governments, banks and listed companies. Public DNS only, read once a month. The sample is built from Brazil's open company registry (Receita Federal, the email of each active head office) and the CVM register of listed companies. Only totals: no domain is listed. A share is `count / (com_mx - dmarc.nao_lido)`; domains without MX are left out. Only the DMARC policy classifies; SPF is counted but does not change the class. `percent` rounds each group to 100 by the largest remainder, the same rule as the page. - **URL:** `https://staging.commsharbor.com/api/email-raio-x` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `mes` (string) — Month of the reading, `YYYY-MM` (UTC). - `medido_em` (string) — ISO time when the reading finished. - `amostra` (string) — Date of the domain list, `YYYY-MM-DD`. - `grupos` (object) — Totals by group: `prefeituras` (city halls), `governos_estaduais`, `governo_federal`, `bancos`, `companhias_abertas` (listed companies) and `varejo` (listed retailers), each with the fields of `total`. A domain can be in two groups, so the groups add up to more than `total`. - `total` (object) — `{dominios, com_mx, sem_mx, mx_nao_lido, dmarc, spf, percent}`: domains in the sample and how many receive email (with MX). Among those, `dmarc` counts `reject`, `quarantine`, `none`, `ausente` (no record) and `nao_lido` (the DNS answer failed); `spf` counts the ending: `hardfail` (-all), `softfail` (~all), `fraco` (?all, +all or no ending), `ausente`, `multiplo` and `nao_lido`. `percent` has the whole-number shares of `ausente`, `none`, `quarantine` and `reject`, which add up to 100, and `nao_rejeitam` (100 minus `reject`): the numbers on the page. `null` when no DMARC answer was read. - `method` (string) — How the reading was made. - `page` (string) — Public page with the report, in English. - `page_pt` (string) — Public page with the report, in Portuguese. **Errors** - `503` — report_not_ready: the first monthly reading is still running; retry in an hour. **Example** ```sh curl -s "https://staging.commsharbor.com/api/email-raio-x" ``` ## Subscriptions ### `GET /api/credito/assinaturas` List at most 20 subscriptions owned by this account in this product. Requires enabled subscription sales or a server-authorized payment test. Otherwise returns 404. Filters account, product, merchant and environment. Does not query Asaas or count the table. The accepted offer remains readable after sales close. Sandbox reads require a valid ticket. The complete query is limited to 640 characters, including the cursor. - **URL:** `https://staging.commsharbor.com/api/credito/assinaturas` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Query** - `dev` (string) — Valid signed payment-test ticket. At most 512 characters. It never authorizes another account. - `x402_dev` (string) — Alias for dev. Send only one of these parameters. - `cursor` (string) — proximo from the previous page: UTC ISO time with milliseconds, ~ and a 32-character hexadecimal ID. - `recurso` (string) — Product resource: at most 256 characters without controls. Filters this account's subscriptions. **Headers** - `X-X402-Dev` (string) — Valid signed payment-test ticket. The request body's sandbox flag does not authorize a test. **Response `200`** - `itens` (RegistroDeAssinatura[]) — At most 20 records owned by this account. → see `RegistroDeAssinatura` under **Structures**. - `proximo` (string, may be null) — Next-page cursor, or null. - `simulado` (bool) — Server-authorized environment for this request. - `recursos` (object) — Optional for organization subscriptions: maps resource IDs on this page and its filter to names verified in this account's organizations; null when the name is not authorized. Never uses a name from the URL. **Errors** - `400` — Invalid body, query, offer, acceptance, card or environment; card declined. - `401` — Missing or invalid session. An API key cannot authorize these requests. - `403` — Invalid origin or cookie; invalid CSRF protection on a write. - `404` — Sales and payment tests are unavailable, or the subscription is outside this account, product, merchant or environment. - `431` — Cookie header exceeds 8 KiB. - `503` — Account, database, configuration or provider unavailable; four concurrent operations already in progress. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/assinaturas -b sessao.cookies ``` ### `GET /api/credito/assinaturas/ofertas` Read the subscription offers and request environment when enabled. Requires enabled subscription sales or a server-authorized payment test. Otherwise returns 404. Creates no charge, reservation or benefit. Does not convert a trial into a purchase. - **URL:** `https://staging.commsharbor.com/api/credito/assinaturas/ofertas` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Query** - `dev` (string) — Valid signed payment-test ticket. At most 512 characters. It never authorizes another account. - `x402_dev` (string) — Alias for dev. Send only one of these parameters. **Headers** - `X-X402-Dev` (string) — Valid signed payment-test ticket. The request body's sandbox flag does not authorize a test. **Response `200`** - `ofertas` (OfertaDeAssinatura[]) — 1 to 8 versioned offers for this product. → see `OfertaDeAssinatura` under **Structures**. - `simulado` (bool) — Server-authorized environment for this request. **Errors** - `400` — Invalid body, query, offer, acceptance, card or environment; card declined. - `404` — Sales and payment tests are unavailable, or the subscription is outside this account, product, merchant or environment. - `503` — Account, database, configuration or provider unavailable; four concurrent operations already in progress. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/assinaturas/ofertas ``` ### `POST /api/credito/assinaturas` Subscribe and pay for the selected offer by card through the API. Requires enabled subscription sales or a server-authorized payment test. Otherwise returns 404. Requires a human session authenticated within the last 2 hours. Rejects Authorization and X-Api-Key. Send only the declared fields, with HTTPS and a JSON body of at most 4 KiB. recurso is accepted only when the product verifies it. simulado must match the catalog and authorized environment. An expired test ticket cannot change the request to production. Price and benefits come from the server. Card data goes to Asaas for this request only; it is not stored or returned. The server supplies the buyer IP. Allow up to 120 seconds. A repeated offer returns the existing reservation. An uncertain outcome requires a reference lookup before another creation. Creation grants no benefit. Only an Asaas-confirmed payment grants the paid period. - **URL:** `https://staging.commsharbor.com/api/credito/assinaturas` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Query** - `dev` (string) — Valid signed payment-test ticket. At most 512 characters. It never authorizes another account. - `x402_dev` (string) — Alias for dev. Send only one of these parameters. **Headers** - `X-X402-Dev` (string) — Valid signed payment-test ticket. The request body's sandbox flag does not authorize a test. - `Origin` (string, required) — Exact HTTPS origin of this product. - `X-CSRF-Token` (string, required) — 64-character token from this product's session bootstrap. Required for writes. **Body** (`application/json`) - `recurso` (string) — Required when the product sells per resource. The server verifies the resource and account. - `simulado` (bool, required) — Value from the catalog. States intent; grants no payment-test authority. - `aceite` (AceiteDeAssinatura, required) — Only oferta_id, versao, hash and renovacao. Match the current catalog. - `cartao` (CartaoDeAssinatura, required) — Cardholder's card and billing data. Do not send price, IP, environment or another account's identifier. **Response `200`** Structure: `RegistroDeAssinatura`. - `recurso` (string) — Product resource: at most 256 characters, without controls. Empty means an account subscription. - `id` (string) — Local subscription ID: 32 lowercase hexadecimal characters. Use it for reads and cancellation. - `oferta_id` (string) — Accepted offer ID. - `oferta` (OfertaDeAssinatura) — Offer saved at acceptance. A catalog change does not replace this record. → see `OfertaDeAssinatura` under **Structures**. - `estado` (string) — criando, inconclusiva, checkout, aguardando_pagamento, ativa, cancelando, cancelada, falhou or expirada. - `simulado` (bool) — Server-recorded environment: true for sandbox, false for production. - `pagamento_em` (string, may be null) — Null for API card purchases. Older checkout records can contain an Asaas HTTPS link. - `criado_em` (string) — Subscription creation time in UTC. - `atualizado_em` (string) — Last change time in UTC. - `cancelamento_em` (string, may be null) — Cancellation request time in UTC, or null. - `cancelado_em` (string, may be null) — Confirmed cancellation time in UTC, or null. - `pago_ate` (string, may be null) — On reads and cancellation, UTC end of the last period with a confirmed, non-refunded invoice; null without a paid invoice. It is not the next charge date or the free trial. **Errors** - `400` — Invalid body, query, offer, acceptance, card or environment; card declined. - `401` — Missing or invalid session. An API key cannot authorize these requests. - `403` — Invalid origin or cookie; invalid CSRF protection on a write. - `404` — Sales and payment tests are unavailable, or the subscription is outside this account, product, merchant or environment. - `409` — Incompatible state or another offer already reserved for this account and product. - `413` — JSON body exceeds 4 KiB. - `415` — Body is not application/json or has content encoding. - `429` — This account reached its daily charge-creation limit. - `431` — Cookie header exceeds 8 KiB. - `503` — Account, database, configuration or provider unavailable; four concurrent operations already in progress. **Example** ```sh curl -s -X POST https://staging.commsharbor.com/api/credito/assinaturas -b sessao.cookies -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "content-type: application/json" --data-binary @contratacao.json ``` ### `GET /api/credito/assinaturas/:id` Read an owned subscription and its accepted offer without creating a payment. Requires enabled subscription sales or a server-authorized payment test. Otherwise returns 404. Requires this product's valid human session. Does not query the provider. Sandbox reads also require a valid ticket. - **URL:** `https://staging.commsharbor.com/api/credito/assinaturas/:id` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Path parameters** - `id` (string, required) — Local subscription ID: 32 lowercase hexadecimal characters. e.g.: `0123456789abcdef0123456789abcdef`. **Query** - `dev` (string) — Valid signed payment-test ticket. At most 512 characters. It never authorizes another account. - `x402_dev` (string) — Alias for dev. Send only one of these parameters. - `recurso` (string) — Product resource: at most 256 characters without controls. Filters this account's subscriptions. **Headers** - `X-X402-Dev` (string) — Valid signed payment-test ticket. The request body's sandbox flag does not authorize a test. **Response `200`** Structure: `RegistroDeAssinatura`. - `recurso` (string) — Product resource: at most 256 characters, without controls. Empty means an account subscription. - `id` (string) — Local subscription ID: 32 lowercase hexadecimal characters. Use it for reads and cancellation. - `oferta_id` (string) — Accepted offer ID. - `oferta` (OfertaDeAssinatura) — Offer saved at acceptance. A catalog change does not replace this record. → see `OfertaDeAssinatura` under **Structures**. - `estado` (string) — criando, inconclusiva, checkout, aguardando_pagamento, ativa, cancelando, cancelada, falhou or expirada. - `simulado` (bool) — Server-recorded environment: true for sandbox, false for production. - `pagamento_em` (string, may be null) — Null for API card purchases. Older checkout records can contain an Asaas HTTPS link. - `criado_em` (string) — Subscription creation time in UTC. - `atualizado_em` (string) — Last change time in UTC. - `cancelamento_em` (string, may be null) — Cancellation request time in UTC, or null. - `cancelado_em` (string, may be null) — Confirmed cancellation time in UTC, or null. - `pago_ate` (string, may be null) — On reads and cancellation, UTC end of the last period with a confirmed, non-refunded invoice; null without a paid invoice. It is not the next charge date or the free trial. **Errors** - `400` — Invalid body, query, offer, acceptance, card or environment; card declined. - `401` — Missing or invalid session. An API key cannot authorize these requests. - `403` — Invalid origin or cookie; invalid CSRF protection on a write. - `404` — Sales and payment tests are unavailable, or the subscription is outside this account, product, merchant or environment. - `431` — Cookie header exceeds 8 KiB. - `503` — Account, database, configuration or provider unavailable; four concurrent operations already in progress. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/assinaturas/0123456789abcdef0123456789abcdef -b sessao.cookies ``` ### `POST /api/credito/assinaturas/:id` Stop future charges for an owned subscription and keep the paid period. Requires enabled subscription sales or a server-authorized payment test. Otherwise returns 404. Send only {} as JSON, with a valid session, origin and CSRF token. The server records cancellation intent before it calls Asaas. Pending is not confirmed cancellation. The request is repeatable. Refunds have a separate process; cancellation does not refund a payment. - **URL:** `https://staging.commsharbor.com/api/credito/assinaturas/:id` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Path parameters** - `id` (string, required) — Local subscription ID: 32 lowercase hexadecimal characters. e.g.: `0123456789abcdef0123456789abcdef`. **Query** - `dev` (string) — Valid signed payment-test ticket. At most 512 characters. It never authorizes another account. - `x402_dev` (string) — Alias for dev. Send only one of these parameters. - `recurso` (string) — Product resource: at most 256 characters without controls. Filters this account's subscriptions. **Headers** - `X-X402-Dev` (string) — Valid signed payment-test ticket. The request body's sandbox flag does not authorize a test. - `Origin` (string, required) — Exact HTTPS origin of this product. - `X-CSRF-Token` (string, required) — 64-character token from this product's session bootstrap. Required for writes. **Body example** ```json {} ``` **Response `200`** Structure: `RegistroDeAssinatura`. - `recurso` (string) — Product resource: at most 256 characters, without controls. Empty means an account subscription. - `id` (string) — Local subscription ID: 32 lowercase hexadecimal characters. Use it for reads and cancellation. - `oferta_id` (string) — Accepted offer ID. - `oferta` (OfertaDeAssinatura) — Offer saved at acceptance. A catalog change does not replace this record. → see `OfertaDeAssinatura` under **Structures**. - `estado` (string) — criando, inconclusiva, checkout, aguardando_pagamento, ativa, cancelando, cancelada, falhou or expirada. - `simulado` (bool) — Server-recorded environment: true for sandbox, false for production. - `pagamento_em` (string, may be null) — Null for API card purchases. Older checkout records can contain an Asaas HTTPS link. - `criado_em` (string) — Subscription creation time in UTC. - `atualizado_em` (string) — Last change time in UTC. - `cancelamento_em` (string, may be null) — Cancellation request time in UTC, or null. - `cancelado_em` (string, may be null) — Confirmed cancellation time in UTC, or null. - `pago_ate` (string, may be null) — On reads and cancellation, UTC end of the last period with a confirmed, non-refunded invoice; null without a paid invoice. It is not the next charge date or the free trial. **Errors** - `400` — Invalid body, query, offer, acceptance, card or environment; card declined. - `401` — Missing or invalid session. An API key cannot authorize these requests. - `403` — Invalid origin or cookie; invalid CSRF protection on a write. - `404` — Sales and payment tests are unavailable, or the subscription is outside this account, product, merchant or environment. - `409` — Incompatible state or another offer already reserved for this account and product. - `413` — JSON body exceeds 4 KiB. - `415` — Body is not application/json or has content encoding. - `431` — Cookie header exceeds 8 KiB. - `503` — Account, database, configuration or provider unavailable; four concurrent operations already in progress. **Example** ```sh curl -s -X POST https://staging.commsharbor.com/api/credito/assinaturas/0123456789abcdef0123456789abcdef -b sessao.cookies -H "Origin: https://staging.commsharbor.com" -H "X-CSRF-Token: $CSRF" -H "content-type: application/json" -d '{}' ``` ### `GET /api/credito/assinaturas/:id/estado` Observe changes to an owned subscription through the realtime channel. Requires enabled subscription sales or a server-authorized payment test. Otherwise returns 404. Requires this product's human session. Returns only ID and cursor, including after reconnection. A signal grants no paid access and exposes no financial data. Read the authenticated subscription after a change. That read still verifies environment, merchant and resource. - **URL:** `https://staging.commsharbor.com/api/credito/assinaturas/:id/estado` - **Auth:** `session` — Shared account session: HttpOnly cookie `__Host-mm-auth` (sign in at `/conta/global`); writes need the same Origin, the `__Host-mm-auth-browser` cookie and `X-CSRF-Token` from `/api/auth/bootstrap`. No organization is implied. **Path parameters** - `id` (string, required) — Local subscription ID: 32 lowercase hexadecimal characters. e.g.: `0123456789abcdef0123456789abcdef`. **Query** - `dev` (string) — Valid signed payment-test ticket. At most 512 characters. It never authorizes another account. - `x402_dev` (string) — Alias for dev. Send only one of these parameters. **Headers** - `X-X402-Dev` (string) — Valid signed payment-test ticket. The request body's sandbox flag does not authorize a test. **Response `200`** - `id` (string) — Local subscription ID: 32 lowercase hexadecimal characters. - `cursor` (string) — State version. Compare for equality. It does not confirm a payment. **Errors** - `400` — Invalid body, query, offer, acceptance, card or environment; card declined. - `401` — Missing or invalid session. An API key cannot authorize these requests. - `403` — Invalid origin or cookie; invalid CSRF protection on a write. - `404` — Sales and payment tests are unavailable, or the subscription is outside this account, product, merchant or environment. - `431` — Cookie header exceeds 8 KiB. - `503` — Account, database, configuration or provider unavailable; four concurrent operations already in progress. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/assinaturas/0123456789abcdef0123456789abcdef/estado -b sessao.cookies ``` ## Credit ### `GET /api/credito/x402/saude` x402 verifier health: pending payments, missing hashes, failed or stalled reconciliation. - **URL:** `https://staging.commsharbor.com/api/credito/x402/saude` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `verificado_em` (string) — Reading time in UTC. - `ativo` (boolean) — Verifier configured in this process. → see `boolean` under **Structures**. - `tarefas` (object[]) — Failures with id and reason, without payer data. Bounded counts show +. **Errors** - `503` — Verifier unavailable in this process. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/x402/saude ``` ### `GET /api/credito/barrados/saude` People who paid and were blocked on this site in the last 24 hours: the site asked for payment from someone with balance or a plan, or charged and did not deliver. - **URL:** `https://staging.commsharbor.com/api/credito/barrados/saude` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `verificado_em` (string) — Reading time in UTC. - `ativo` (boolean) — The reading worked. → see `boolean` under **Structures**. - `total` (int) — Number of different cases. - `tarefas` (object[]) — Up to 8 cases, with class, route, count and last time, without payer data. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/barrados/saude ``` ### `GET /api/credito/conta` The balance of the session account: the sum of its purchases in this environment, in every product, without the code. With movimentos=1, the statement of the account. - **URL:** `https://staging.commsharbor.com/api/credito/conta` - **Auth:** `credito` — Credit token in `Authorization: Bearer cred_…` or `X-Credito`. For recovered x402 funds, use the wallet credential mmw_… in Bearer or X-Wallet-Token, issued through /api/auth/wallet/agent/start and /api/auth/wallet/agent/token. **Query** - `movimentos` (string) — `1`: reads only the paged statement of the account, without the balance. - `de` (string) — Inclusive start in UTC ISO 8601 with milliseconds. Default: 1970-01-01T00:00:00.000Z. - `ate` (string) — Exclusive end in UTC ISO 8601 with milliseconds. Default: now. Keep the value between pages. - `antes` (string) — The `proximo` cursor of the previous page. Only with movimentos=1. - `limite` (int) — 1 to 50 entries per page; default 20. Only with movimentos=1. **Response `200`** - `saldo_micros` (int) — The balance in millionths of a dollar. - `saldo_usd` (string) — The balance in dollars, formatted. - `referencia_usd` (string) — The balance right after the last top-up, added across the wallets with a balance: the base of what is left. - `cotacao_brl_por_usd` (number) — The BRL rate the screen uses to show the balance. - `movimentos` (object[]) — Only with movimentos=1: id, em, valor_usd, saldo_usd, motivo, produto and recurso, newest first. - `proximo` (string) — Only with movimentos=1: the cursor of the next page or null. **Errors** - `400` — Invalid period, limit or cursor. - `401` — No session. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/conta -H 'Cookie: ' ``` ### `POST /api/credito/conta` Links credit bought without an account to the account of the session, USDC included. Then the balance works in the products of the shared credit with `X-Credito: conta`, added to the other purchases of the account. - **URL:** `https://staging.commsharbor.com/api/credito/conta` - **Auth:** `credito` — Credit token in `Authorization: Bearer cred_…` or `X-Credito`. For recovered x402 funds, use the wallet credential mmw_… in Bearer or X-Wallet-Token, issued through /api/auth/wallet/agent/start and /api/auth/wallet/agent/token. **Response `200`** - `ok` (boolean) — The link was checked. → see `boolean` under **Structures**. - `ligadas` (int) — Purchases linked now. Zero when the purchase already has an account. - `da_conta` (boolean) — The balance of this code is already in the account balance. → see `boolean` under **Structures**. **Errors** - `401` — No session or no credit code. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/credito/conta -H 'Authorization: Bearer cred_…' -H 'Cookie: ' ``` ### `POST /api/credito` Top up prepaid credit: pay once with x402 and get the token that debits on any API of the house. - **URL:** `https://staging.commsharbor.com/api/credito` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Query** - `usd` (number, required) — Package: 0.1, 1, 5, 10 or 25 dollars. **Response `200`** - `token` (string) — Bearer token for the balance (`cred_…`). Shown ONCE — it cannot be recovered. - `saldo_usd` (string) — Credited balance. - `guarde` (string) — Warning that the token is the bearer of the credit. - `usar` (string) — How to present the token on paid routes. - `usar_com_outra_credencial` (string) — The `X-Credito` header, for when `Authorization` already carries another credential. - `saldo_em` (string) — Where to check balance and statement. - `onde_gastar` (object) — `precos`: the paid actions and prices of this product (`/api/pricing`); `produtos`: the APIs.json with our other products. **Errors** - `400` — Package outside the list (0.1, 1, 5, 10 or 25). - `402` — Unpaid — the body carries the x402 `accepts[]`. **Example** ```sh curl -s -XPOST 'https://staging.commsharbor.com/api/credito?usd=10' ``` ### `GET /api/credito` Balance and statement with cred_…; wallet balance and up to 20 recovery records with mmw_…. A request without a token receives 401. The Link header points to the x402 manifest. When billing is configured, accepts[] contains the same terms as the smallest POST top-up. GET cannot charge or create credit. - **URL:** `https://staging.commsharbor.com/api/credito` - **Auth:** `credito` — Credit token in `Authorization: Bearer cred_…` or `X-Credito`. For recovered x402 funds, use the wallet credential mmw_… in Bearer or X-Wallet-Token, issued through /api/auth/wallet/agent/start and /api/auth/wallet/agent/token. **Response `200`** - `saldo_micros` (int) — Balance in micro-dollars (1e-6 USD). - `saldo_usd` (string) — Formatted balance. - `criado_em` (string) — When the credit was opened. - `movimentos` (object[]) — Recent credits and debits, with product and resource. - `wallet` (string) — Only with mmw_…: authenticated wallet address. - `payments` (object[]) — Only with mmw_…: up to 20 payments with id, produto, rede, tx_hash, micros, estado and criado_ms. creditado means recovered balance. - `onde_gastar` (object) — `precos`: the paid actions and prices of this product; `produtos`: the APIs.json with our other products. **Errors** - `401` — No token, or unknown token. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito -H 'Authorization: Bearer cred_…' ``` ### `GET /api/credito/pix` Credit by Pix (Brazil): the key, the fixed rate, the packs in reais and what the receipt accepts. - **URL:** `https://staging.commsharbor.com/api/credito/pix` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `chave` (string) — The Pix key that receives the payment. - `brl_por_usd` (number) — Fixed rate used for the packs. - `pacotes` (object[]) — The packs (3, 5, 10 or 25 dollars), each with `brl_centavos` and `copia_e_cola` (the Pix copy-and-paste code for the amount, the same text as the QR: the bank app comes with the amount filled in). - `comprovante` (object) — Accepted types (photo or PDF) and the maximum size, in bytes. - `liberacao` (string) — `manual`: the owner checks the Pix and releases it. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/pix ``` ### `POST /api/credito/pix` Request credit paid by Pix: multipart with `usd`, `comprovante` (photo or PDF up to 2 MB) and `email`; the rest is optional. The credit code comes back in the response and works once the owner checks the Pix and releases it (by hand, usually the same day). `email` is required: it is how the owner reaches the person. Optional: `nome`, `pagina` (the page the request came from, up to 2,000 characters) and what the person was buying when the 402 came — `recurso` (up to 2,000), `descricao` (up to 300) and `preco_usd` (decimal, e.g. `0.50`); and `navegador_id` (a UUID that links the requests from the same browser). Everything that arrives is recorded with the request — the receipt included —, with the signed-in account (checked by the session cookie), the network and browser. - **URL:** `https://staging.commsharbor.com/api/credito/pix` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `id` (string) — Request id, to follow it. - `estado` (string) — `pendente` until the decision. - `credito` (string) — The `cred_…` token, shown ONCE; it works after the release. - `estado_em` (string) — Where to follow the request. **Errors** - `400` — Pack outside the list (3, 5, 10 or 25), no receipt or no valid e-mail. - `413` — Receipt above 2 MB. - `415` — Receipt that is neither a photo (JPEG, PNG, WebP) nor a PDF. - `429` — This network already sent today's requests. - `502` — The e-mail to the owner did not go out: the request is recorded as `falhou`; send it again. - `503` — Review queue full, or Pix not available in this app. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/credito/pix -F usd=5 -F email=you@company.com -F comprovante=@pix.pdf ``` ### `GET /api/credito/pix/:id` Status of a Pix credit request: `pendente`, `liberado`, `recusado` or `falhou`. - **URL:** `https://staging.commsharbor.com/api/credito/pix/:id` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Path parameters** - `id` (string, required) — Request id (32 hex). e.g.: `0123456789abcdef0123456789abcdef`. **Response `200`** - `estado` (string) — `pendente`, `liberado`, `recusado` or `falhou` (the e-mail to the owner did not go out; send again). - `usd` (int) — The requested pack. - `decidido_em` (string) — When the owner decided, or `null`. **Errors** - `404` — Unknown request. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/pix/0123456789abcdef0123456789abcdef ``` ## Crédito ### `POST /api/credito/asaas/:id/cancelar` Cancels a pending charge when the payment dialog closes. Requires the `cancelamento` capability returned at creation. An older credit charge accepts its token in `credito`. The product and environment must match. This does not refund payments or remove records. 202 means cancellation is pending; the scheduled worker retries provider failures. - **URL:** `https://staging.commsharbor.com/api/credito/asaas/:id/cancelar` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Path parameters** - `id` (string, required) — Charge id (32 hex). e.g.: `0123456789abcdef0123456789abcdef`. **Response `200`** - `id` (string) — Charge id. - `estado` (string) — `cancelando`, `vencido`, or the confirmed final state. **Errors** - `404` — Invalid charge or capability, or a different product or environment. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/credito/asaas/0123456789abcdef0123456789abcdef/cancelar -H 'content-type: application/json' -d '{"cancelamento":""}' ``` ### `GET /api/credito/asaas` Automatic Pix: whether it is available in this app, the packs in reais and the balance the product sells. - **URL:** `https://staging.commsharbor.com/api/credito/asaas` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `disponivel` (boolean) — `false` when the app has no Asaas configured (use the Pix with receipt). → see `boolean` under **Structures**. - `pacotes` (object[]) — The credit packs (3, 5, 10 or 25 dollars), with `brl_centavos`. - `exatos` (object[]) — Prices declared by the app, with `usd` and `brl_centavos`. Amounts start at R$ 5.00 and cannot exceed R$ 10,000. - `saldo` (object) — When the product sells a balance in reais: the range and whether the account can buy. - `precisa_documento` (boolean) — Whether the payer's CPF or CNPJ is still required. → see `boolean` under **Structures**. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/asaas ``` ### `POST /api/credito/asaas` Creates a dynamic Pix: JSON with `oferta` (`pacote` with `usd`, or `saldo` with `centavos`) and the payer. The payment releases what was bought by itself: the pack becomes the `cred_…` token already in the response; the balance goes to the logged-in account's organization. The first purchase needs `documento` (CPF or CNPJ, sent to the gateway and not stored here) and `nome`; `email`, `pagina` and `navegador_id` are optional. With `forma: "cartao_boleto"` the charge is open: the response brings `pagamento_em`, the gateway page where you pay by card, boleto or Pix (due in three days). With `forma: "cartao"` and `cartao` (`titular`, `numero`, `mes`, `ano`, `cvv`, `documento`, `email`, `cep`, `numero_endereco`, `telefone`), the charge is paid by card in the same request: 200 with `estado: "pago"`, 202 with `conferir` while the issuer reviews it, 422 when the card is declined; the card is not stored. Set `usd` to an amount from `pacotes` or `exatos` in the GET response. The server sets the amount in cents and rejects amounts that the app has not declared. - **URL:** `https://staging.commsharbor.com/api/credito/asaas` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `id` (string) — Charge id, to follow up. - `credito` (string) — For a pack: the `cred_…` token, shown ONCE; valid when the payment arrives. - `forma` (string) — `pix` (the default), `cartao` or `cartao_boleto`. - `pix` (object) — `copia_e_cola`, `imagem` (PNG QR, data URI) and `expira_em`; `pix` form only. - `pagamento_em` (string) — In the `cartao_boleto` form: the gateway payment page. - `estado` (string) — In the `cartao` form: `pago`, or `pendente` with `conferir`. - `estado_em` (string) — Where to follow the payment. - `cancelamento` (string) — Capability to cancel a pending Pix or boleto charge. **Errors** - `400` — Credit amount outside `pacotes` and `exatos`, amount out of range, invalid CPF/CNPJ, name or e-mail, invalid card data (`cartao_dados`, with the `campo`), or the gateway refused the payer (`pagador_recusado`, with the reason in `detalhe`). - `422` — Card declined (`cartao_recusado`, with the `campo` when the gateway says which); try another card with `POST /api/credito/asaas/:id/cartao`. - `429` — Limit of 3 attempts per minute or 10 per day, per account or network, or the card limit. - `502` — The gateway did not create the Pix; try again. - `503` — Automatic Pix unavailable in this app, the gateway is busy (`asaas_ocupado`, wait `retry_after_s`), or too many charges from people not signed in waiting for payment. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/credito/asaas -H 'content-type: application/json' -d '{"oferta":"pacote","usd":5,"documento":"000.000.000-00","nome":"Ana"}' ``` ### `GET /api/credito/asaas/:id` State of an automatic Pix charge: `pendente`, `pago`, `vencido`, `estornado` or `falhou`. - **URL:** `https://staging.commsharbor.com/api/credito/asaas/:id` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Path parameters** - `id` (string, required) — Charge id (32 hex). e.g.: `0123456789abcdef0123456789abcdef`. **Response `200`** - `estado` (string) — `pago` releases the pack token or the balance; a Pix paid after the due date counts. - `pago_em` (string) — When the payment was confirmed, or `null`. **Errors** - `404` — Unknown charge. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/asaas/0123456789abcdef0123456789abcdef ``` ### `POST /api/credito/asaas/:id/cartao` Pays a card charge whose card was declined with another card: the same charge, never charged twice. JSON with the `cartao` (the same fields as `POST /api/credito/asaas`) and, without an account, the `navegador_id` that created the charge. Only a card charge waiting for payment, by whoever created it, and up to five attempts per charge. - **URL:** `https://staging.commsharbor.com/api/credito/asaas/:id/cartao` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Path parameters** - `id` (string, required) — Id da cobrança (32 hex). e.g.: `0123456789abcdef0123456789abcdef`. **Response `200`** - `estado` (string) — `pago`, or `pendente` with `conferir` while the issuer reviews it. - `estado_em` (string) — Where to follow the payment. **Errors** - `400` — Invalid card data (`cartao_dados`, with the `campo`). - `404` — Unknown charge, someone else's charge, or not a card charge. - `409` — The charge expired or was closed; start the payment again. - `422` — Card declined (`cartao_recusado`). - `429` — Used up the card attempts for this charge or for today. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/credito/asaas/0123456789abcdef0123456789abcdef/cartao -H 'content-type: application/json' -d '{"cartao":{…}}' ``` ### `GET /api/credito/asaas/saude` Health of this app's Pix and enabled subscriptions: failures and reasons for the dashboard. - **URL:** `https://staging.commsharbor.com/api/credito/asaas/saude` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `ativo` (boolean) — `false` when Asaas and subscriptions are disabled. → see `boolean` under **Structures**. - `tarefas` (object[]) — Each problem has `id`, `falhando`, and `motivo`. Includes Pix and, when enabled, subscription recovery, queue, and budget. Does not call the provider. **Example** ```sh curl -s https://staging.commsharbor.com/api/credito/asaas/saude ``` ## Operations ### `POST /api/erro-cliente` Browser error report, sent by the interface itself. Agents need not call it. The interface reports on its own JS errors, unhandled rejections, scripts/CSS that failed to load and CSP blocks — once per session — and the app reports handled failures through `window.mmErro.relata`. The server validates the envelope, redacts credentials, e-mails and phone numbers, merges repeats of the same failure per minute and records an operational event; nothing is written to a database. It keeps no IP, cookie, query string or full User-Agent. Always answers 204, even for an invalid report. - **URL:** `https://staging.commsharbor.com/api/erro-cliente` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Body** (`application/json`) - `code` (string, required) — Failure code, `UI-` + letters/digits (`UI-JS-001` global error, `UI-PROMESSA-001`, `UI-RECURSO-001`, `UI-CSP-001`, `UI-APP-001` app report). - `phase` (string, required) — Where it broke, lowercase: `global`, `promessa`, `script`, `load_list`… - `path` (string) — Path of the open page, without query; numbers, hashes and tokens in it are kept as `:id`. - `message` (string) — Error message, up to 2000 characters. - `stack` (string) — Stack trace, up to 12000 characters. - `source` (string) — Originating script; only its path is kept. - `line` (int) — Line in the originating script. - `column` (int) — Column in the originating script. - `visivel` (bool) — Whether the tab was visible when it broke. - `build` (string) — Build of the reporting page (its ``), up to 64 letters, digits, `.`, `_` or `-`; it dates the failure. **Body example** ```json { "code": "UI-APP-001", "phase": "carregar_lista", "path": "/", "message": "lista 500" } ``` **Response `200`** 204 with no body, always — an invalid, repeated or over-cap report also gets 204. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/erro-cliente -H 'content-type: application/json' -d '{"code":"UI-APP-001","phase":"carregar_lista","path":"/","message":"lista 500"}' ``` ### `POST /api/pagamento/aberto` The interface reports a visible payment prompt. Agents must not call this route. An empty same-origin report, sent automatically when a payment prompt becomes visible. It starts no payment, grants no access and receives no identity or credentials. It writes no database row per report. Counts events, not unique people. The private operator dashboard separates API payment requests and browser payment views per UTC day; the two counts may overlap. - **URL:** `https://staging.commsharbor.com/api/pagamento/aberto` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Headers** - `Origin` (string, required) — The page origin, identical to this route's origin. - `Sec-Fetch-Site` (string, required) — `same-origin`, set by the browser. - `X-MM-Payment-View` (string, required) — `1`, set by the shared component. **Response `202`** 202 with no body when accepted; 204 when ignored. Always no-store. ### `POST /api/funil` The interface reports the steps of a visit (conversion funnel). Agents must not call this route. A same-origin batch sent by the page itself: page views, engagement, offer in view, buy click, payment window, payment sent or accepted. It keeps the browser's random id, the path without query, the referring host and the utm tags; never IP, e-mail or account. It writes no database row: one line per batch in the day's journal, with a cap. Declared robots and smoke tests are left out. - **URL:** `https://staging.commsharbor.com/api/funil` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Headers** - `Origin` (string) — The page origin, identical to this route's origin. - `Content-Type` (string, required) — `application/json` or `text/plain`. **Body** (`application/json`) - `v` (number, required) — Batch version: `1`. - `vid` (string, required) — This browser's random id (UUID v4). - `sid` (string, required) — Session id (30 idle minutes end it). - `sn` (number, required) — This browser's session number. - `pv` (string, required) — Page view id. - `e` (object[], required) — Up to 40 events `{ t, n, p? }` from the funnel vocabulary. **Response `202`** 202 with no body when stored; 204 when ignored. Always no-store. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/funil -H 'content-type: text/plain' -H 'x-mm-smoke: 1' -d '{"v":1,"vid":"0f8b9c1e-2a3b-4c5d-8e6f-7a8b9c0d1e2f","sid":"s1abcdefgh","sn":1,"pv":"p1abcdefgh","e":[{"t":0,"n":"pagina"}]}' ``` ### `GET /api/funil/arquivos` Operator: the funnel journal days kept by this app, with the size of each. - **URL:** `https://staging.commsharbor.com/api/funil/arquivos` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Headers** - `Authorization` (string, required) — `Bearer `. **Response `200`** - `v` (number) — Stored batch version. - `produto` (string) — The product. - `teto` (object) — `bytesDia` and `dias` kept. - `dias` (object[]) — `{ dia, bytes }`, oldest to today. **Errors** - `401` — Unauthorized - `503` — Not configured **Example** ```sh curl -s https://staging.commsharbor.com/api/funil/arquivos -H "Authorization: Bearer $METRICS_TOKEN" ``` ### `GET /api/funil/arquivo` Operator: a slice of one funnel journal day, as NDJSON, from a byte offset. Up to 4 MiB per response, cut at the last whole line. `X-MM-Funil-Proximo` says where to ask for the rest; `X-MM-Funil-Tamanho`, the day's size now. - **URL:** `https://staging.commsharbor.com/api/funil/arquivo` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Query** - `dia` (string, required) — The day, `YYYY-MM-DD` (UTC). - `desde` (number) — The byte to read from; `0` at the start. **Headers** - `Authorization` (string, required) — `Bearer `. **Response `200`** JSON lines, one per stored batch. **Errors** - `400` — Invalid parameters - `401` — Unauthorized - `503` — Not configured **Example** ```sh curl -s "https://staging.commsharbor.com/api/funil/arquivo?dia=2026-09-27&desde=0" -H "Authorization: Bearer $METRICS_TOKEN" ``` ### `GET /api/metrics` Last-7-day metrics for the operator dashboard; with the token, payments come along. Without credentials it returns product usage: deliveries per day and organization totals. With `METRICS_TOKEN` as Bearer it adds `payments` — x402 settled on Base mainnet only — and `compras`, who paid in the last 30 days. - **URL:** `https://staging.commsharbor.com/api/metrics` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Headers** - `Authorization` (string) — `Bearer ` to include the financial block; a wrong token is 401. **Response `200`** Structure: `Metricas`. - `app` (string) — Product name. - `today` (string) — Reference day (UTC, YYYY-MM-DD). - `today_visits` (int) — Interface visits counted today. - `today_contacts` (int, optional) — Contact messages today. Only with `METRICS_TOKEN`: contact counts never leave without the token. - `days` (object[]) — One row per day of the window, with each metric's count. - `usage` (object) — `entregas`: deliveries per day — real product usage, not catalog load. - `accounts` (object) — `organizacoes`: total organizations registered. - `financeiro` (object, optional) — Day aggregate: `hoje_usd`, `hoje_count`, `rede`. Only with `METRICS_TOKEN`: money never leaves without the token; the full series is `payments`. - `payments` (object, optional) — x402 and BRL financial summary; METRICS_TOKEN only. - `compras` (object, optional) — Who paid in the last 30 days: up to 20 BRL purchases with name, verified email and use, and the x402 payers by wallet. METRICS_TOKEN only. **Errors** - `401` — Wrong operator token. - `503` — Worker without METRICS_TOKEN configured. **Example** ```sh curl -s https://staging.commsharbor.com/api/metrics -H "Authorization: Bearer $METRICS_TOKEN" ``` ## Public stats ### `GET /api/vitrine` The product's public numbers: traffic, agents, usage and reliability, no money. Projection published hourly by the house collector, rounded to two significant digits; `null` is a missing measurement, never zero. 15-minute cache with ETag (`If-None-Match` → 304). There is no way to send numbers through this route: publishing belongs to the collector, with its own token. - **URL:** `https://staging.commsharbor.com/api/vitrine` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `v` (int) — Contract version (1). - `produto` (string) — Product id. - `publicado` (bool) — `false` before the collector's first publication; then only these five keys come. - `atualizado_em` (string, may be null) — When the collector published (ISO 8601). - `stale` (bool) — `true` when the projection is older than 26 h. - `nome` (string, optional) — Product name. - `desde` (string, optional, may be null) — First day the series covers. - `fuso` (string, optional) — Traffic time zone. Audience periods state their time zone in `pessoas.medicao`. - `hoje` (object, optional) — Today: pages by class (human, AI, bot), API calls by class, machine-surface reads and product usage. - `dias` (object[], optional) — Up to 31 days, oldest first: `dia`, `paginas`, `api`, `api_ia`, `maquina`, `visitantes`, `uso`. - `janelas` (object, optional) — 7- and 30-day sums (`d7`, `d30`). - `visitantes` (object, optional) — Unique browsers with recorded interaction over 7 days. - `pessoas` (object, optional, may be null) — First-party measurement of browsers confirmed by interaction: unique browsers, sessions and pages over 7 and 30 days, segments and coverage. `null` means no measurement. Browsers are not verified people. - `agentes` (object, optional) — The AI agents and bots that read the most, 7 days. - `superficies` (object, optional) — Reads of OKF, llms, well-known, OpenAPI and MCP over 7 days. - `mcp` (object, optional) — MCP calls over 7 days. - `uso` (object, optional) — Real product usage per resource: label, today, 7 and 30 days. - `contas` (object, optional, may be null) — Users and guests. - `confiabilidade` (object, optional) — Share of requests without 5xx over 7 days, and the live build. - `catalogo` (object, optional, may be null) — Size of the catalog, when the product has one. - `apoio` (object, optional) — Measured sponsors: 1-second exposures and native clicks per page in confirmed sessions, 7-day CTR, observed days and coverage. Empty means no history, not zero CTR. **Example** ```sh curl -s https://staging.commsharbor.com/api/vitrine ``` ### `GET /api/vitrine/operador` The product's full document on the operator panel — operator token only. - **URL:** `https://staging.commsharbor.com/api/vitrine/operador` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Headers** - `Authorization` (string, required) — `Bearer ` — the operator class. **Response `200`** - `produto` (string) — Product id. - `atualizado_em` (string, may be null) — When the collector published. - `operador` (object, may be null) — The collector's full document, with what the public projection leaves out. **Errors** - `401` — No token, wrong token or a token of another class. - `503` — Worker without `METRICS_TOKEN` or without the control plane. **Example** ```sh curl -s https://staging.commsharbor.com/api/vitrine/operador -H "Authorization: Bearer $METRICS_TOKEN" ``` ### `GET /api/vitrine/painel` The whole house panel, in the shape the gm reads — operator token only. - **URL:** `https://staging.commsharbor.com/api/vitrine/painel` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Headers** - `Authorization` (string, required) — `Bearer ` — the operator class. **Response `200`** - `apps` (object[]) — One operator document per product, ordered by id. - `updated` (string, optional) — When the collector closed the round. - `totals` (object, optional) — House totals. **Errors** - `401` — No token, wrong token or a token of another class. - `503` — Worker without `METRICS_TOKEN` or without the control plane. **Example** ```sh curl -s https://staging.commsharbor.com/api/vitrine/painel -H "Authorization: Bearer $METRICS_TOKEN" ``` ### `GET /api/vitrine/cursores` Per-product cursors: `borda`, `borda5xx` (5xx only), and `cli`. Operator token only. - **URL:** `https://staging.commsharbor.com/api/vitrine/cursores` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Headers** - `Authorization` (string, required) — `Bearer ` — the operator class. **Response `200`** JSON: `{ [product]: { borda?: ISO, borda5xx?: ISO, cli?: ISO } }`; empty is `{}`. **Errors** - `401` — No token, wrong token or a token of another class. - `503` — Worker without `METRICS_TOKEN` or without the control plane. **Example** ```sh curl -s https://staging.commsharbor.com/api/vitrine/cursores -H "Authorization: Bearer $METRICS_TOKEN" ``` ## Partnership ### `GET /api/partners` Partnerships, integrations and contact. Partnership ideas, public numbers and contact form. Advertising and ad purchases are unavailable. Cached for 1 hour. - **URL:** `https://staging.commsharbor.com/api/partners` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Response `200`** - `status` (string) — `parceria`. - `produto` (string) — Product name. - `idioma` (string) — Language of the texts (the product's). - `titulo` (string) — Title of the offer. - `descricao` (string) — One sentence about the offer. - `publico` (string) — Who uses the product — the audience a sponsor reaches. - `modalidades` (object[]) — `{ id, nome }`: patrocinio, parceria, anuncio. - `placements` (object[]) — [] - `packages` (object[]) — [] - `house_bundle` (object) — `{ disponivel: false }`. - `parcerias` (string[]) — Partnership ideas the product is open to discuss. - `current_sponsors` (object[]) — Sponsors in effect: `id`, `nome`, `url`, `frase`, `espacos`, `ate`. - `stats` (object) — Excerpt of the public numbers (`hoje`, `janelas`, `agentes`, `confiabilidade`) and the `link` to `/api/vitrine`; `publicado: false` before the first publication. - `payment` (object) — `{ disponivel: false }`. - `contact` (object) — `email`, `form_url`, `api_url` (`POST /api/contact`, free: one message every 10 s per network), `campos` (required), `campos_proposta` (the optional proposal fields, each with its accepted values), `message_template`, `instructions`. - `politica` (object) — Refused sectors. - `_links` (object) — `self`, `stats`, `page` (`null` until the page exists), `contact`, `casa` (the same path on the ten products). - `publicidade_disponivel` (bool) — `false`. **Example** ```sh curl -s https://staging.commsharbor.com/api/partners ``` ## Contact ### `POST /api/contact` Write to the people behind the product — free, for people and agents alike. One route for a question and for a sponsorship, partnership or ad proposal (`tipo`, with the placements of `GET /api/partners`). No captcha, no account, no payment. One message every 10 seconds per network: one that arrives sooner waits its turn and then goes out — no error. The message reaches the team by e-mail, with `email` as the reply address. For voice, send multipart/form-data: `dados` is this JSON (up to 32 KiB), and `audio` is one WebM, Ogg or M4A audio file (up to 2 MB). Audio can replace message. The browser records up to two minutes. Audio is attached to the owner's e-mail. - **URL:** `https://staging.commsharbor.com/api/contact` - **Auth:** `none` — Public endpoint. No tenant data is returned. **Body** (`application/json`) - `name` (string, required) — What to call the person writing. - `email` (string, required) — Where to reply. - `message` (string, required) — What you want to say. - `whatsapp` (string) — Optional reply number with country code, such as +5561999999999. - `prefer_whatsapp` (bool) — Request a WhatsApp reply. Requires whatsapp. - `tipo` (string) — Proposal: `patrocinio`, `parceria`, `anuncio` or `consultoria`. Turns on the fields below. - `empresa` (string) — Who is proposing, when it is a company. - `site` (string) — Website of who is proposing. - `orcamento` (string) — Advertising: `ate_100`, `100_500`, `500_2000`, `2000_mais` or `a_combinar`. Consulting, in US dollars: `ate_2000`, `2000_5000`, `5000_10000`, `10000_mais` or `nao_sei`. - `espaco` (string[]) — Placement ids from `GET /api/partners`, up to 6. - `duracao` (string) — Exposure in days: `30`, `90` or `365`. - `pagamento` (string) — `usdc`, `deposito` or `a_combinar`. - `projeto` (string) — Consulting: the kind of project (`llm_privado`, `voz`, `dados_sensiveis`, `gpu`, `integracao` or `outro`). - `prazo` (string) — Consulting: when to start (`agora`, `1_mes`, `1_3_meses` or `explorando`). - `formato` (string) — Consulting: `projeto` (per scope), `mensal` (monthly) or `assessoria` (advisory). - `pais` (string) — Consulting: the country of the person asking. - `fuso` (string) — Consulting: the IANA time zone, such as `America/New_York`. - `horarios` (string[]) — Consulting: up to 3 times for the call, `YYYY-MM-DDTHH:MM` in that time zone. **Body example** ```json { "name": "Agent", "email": "agent@example.com", "message": "hello from an agent" } ``` **Response `200`** - `ok` (bool) — Always `true` when the message was accepted. **Errors** - `400` — Validation: `code` names the field. - `503` — Contact is not configured on this server. **Example** ```sh curl -s -XPOST https://staging.commsharbor.com/api/contact -H 'content-type: application/json' -d '{"name":"Agent","email":"agent@example.com","message":"hello from an agent"}' ``` ## Structures ### `ApiIndex` The self-describing index of the whole API. - `name` (string) — Product name. - `description` (string) — What the product does, in one sentence. - `build` (string) — Deployed commit. - `environment` (string) — Which environment answered: `production` or `local`. - `base_url` (string) — Origin this API is served from. - `docs` (object) — Links to llms.txt, llms-full.txt, openapi.json, the MCP endpoint and the human UI. - `auth` (object) — Every authentication mode and how to obtain it. - `endpoints` (object[]) — Every endpoint with method, path, auth, absolute URL and what it returns. - `mcp` (object) — Remote MCP endpoint and transport. - `mcp_tools` (string[]) — Name of every MCP tool. ### `Health` Liveness and the commit currently serving. Smoke tests wait for their own deploy here instead of racing edge propagation. - `ok` (bool) — Always true when the Worker answers. - `app` (string) — Product name. - `build` (string) — Deployed commit; CI passes the short SHA at deploy time. - `environment` (string) — Which environment answered. - `timestamp` (string) — Response time (UTC, ISO-8601). ### `User` The person behind the session. - `id` (string) — User ID. - `email` (string) — Email address verified by the global account. ### `Profile` Global MM profile. It belongs to the person, edited on the account, not to any organization. - `name` (string) — Name shown in the interface (empty until the person sets one). - `locale` (string) — Preferred language, e.g. `pt-BR` or `en`. - `timeZone` (string) — IANA time zone, e.g. `America/Sao_Paulo`. - `theme` (string) — `light`, `dark` or `system`. - `revision` (int) — Optimistic revision of the profile. ### `Identity` Who the current session or API key resolves to. Read this before a write when you are not sure which organization is active. - `kind` (string) — How the identity was resolved. - `organizationId` (string) — The active organization. - `userId` (string) — The person's shared-account ID (session only). - `sessionId` (string) — Session identifier (session only). - `apiKeyId` (string) — The organization API key's ID (API key only). - `scopes` (string[]) — What the API key may do (API key only): the work permissions, never billing, erasure, exports or audit. - `role` (string, may be null) — Role inside that organization, from the shared account; null with an API key. - `organization` (object) — `{ id, name }` of the active organization; `name` is null with an API key. ### `Organization` A tenant, opened by id. It lives in the shared account (name, members, roles); CommsHarbor adds the plan. Every piece of customer data in this product is scoped to exactly one. - `id` (string) — Organization ID in the shared account, used in every tenant route. - `name` (string, may be null) — Display name, from the shared account; null with an organization API key. - `role` (string, may be null) — Your role in it, from the shared account; null with an organization API key. - `email_workspace` (string) — Tenant-scoped email workspace URL. Read it for the current plan, allowances and resources. ### `PageCamel` The same listing with the cursor in camelCase. Older resources ship it this way and the name is kept because changing it would break clients already reading it. - `items` (AuditEvent[]) — The records on this page. → see `AuditEvent` under **Structures**. - `nextCursor` (string, may be null) — Cursor for the next page; null when there are no more. ### `AuditEvent` One append-only record of something that happened in the organization. Audit is never rewritten. - `id` (string) — Event ID. - `action` (string) — What happened, e.g. `domain.created`. - `actor_user_id` (string, may be null) — Who did it; null when the actor was a key or the system. - `target` (string, may be null) — What it happened to. - `metadata` (object) — Extra context for this action. Never contains recipient PII. - `created_at` (string) — When it happened (UTC). ### `PaymentQuota` - `free` (PaymentFree[]) — Free allowances and their windows. → see `PaymentFree` under **Structures**. - `paid` (PaymentPrice[]) — List prices in USD or in the stated currency; account-only offers are marked. The operation's 402 is the payable quote. → see `PaymentPrice` under **Structures**. - `how_to_pay` (string) — Payment instructions and availability restrictions. - `live` (string, may be null) — Authoritative product quota endpoint. - `free_now` (string[], optional) — SKUs temporarily free despite their list price. - `charged_now` (string[], optional) — SKUs charged at their list price even when free_now has `*`. - `trial` (PaymentTrial, optional) — Registration trial, when offered. → see `PaymentTrial` under **Structures**. ### `VerificacaoAvulsa` The email security audit of one domain, paid per call: the fields of `GET /api/email-check`. - `domain` (string) — Registrable domain that was checked. - `score` (int) — 0 to 100: DMARC up to 40, SPF 20, DKIM 20, MX 10, MTA-STS 5 and BIMI 5. - `rating` (string) — protected (90+), good (70+), at_risk (40+) or exposed. - `findings` (object[]) — `{code, severity}`, most severe first. Codes: dmarc_missing, dmarc_none, spf_plus_all, spf_missing, spf_multiple, dmarc_quarantine, dkim_not_found, spf_neutral, spf_softfail, dmarc_no_reports, mx_missing, mta_sts_missing, bimi_missing. - `spf` (object) — `{record, ending, multiple}`: the first SPF record, its `all` ending and whether there are two. - `dmarc` (object) — `{record, policy, reports}`: policy reject, quarantine, none or null; reports when `rua` is set. - `dkim` (object) — `{found, checked}`: selectors with a published key and the selectors looked up. - `mx` (string[]) — MX records as `priority host`. - `mta_sts` (bool) — An MTA-STS policy record exists. - `bimi` (bool) — A BIMI record exists at the default selector. - `unread` (string[]) — Parts whose DNS query failed (spf, dmarc, dkim, mx, mta_sts, bimi). They have no findings and no points. - `incomplete` (bool) — At least one DNS query failed. - `checked_at` (string) — ISO time of the DNS reading. - `share_url` (string) — Public page with this result. - `badge_url` (string) — SVG badge with the score. - `cobranca` (CobrancaDaChamada) — How this call was paid. → see `CobrancaDaChamada` under **Structures**. ### `RegistroDeAssinatura` - `recurso` (string) — Product resource: at most 256 characters, without controls. Empty means an account subscription. - `id` (string) — Local subscription ID: 32 lowercase hexadecimal characters. Use it for reads and cancellation. - `oferta_id` (string) — Accepted offer ID. - `oferta` (OfertaDeAssinatura) — Offer saved at acceptance. A catalog change does not replace this record. → see `OfertaDeAssinatura` under **Structures**. - `estado` (string) — criando, inconclusiva, checkout, aguardando_pagamento, ativa, cancelando, cancelada, falhou or expirada. - `simulado` (bool) — Server-recorded environment: true for sandbox, false for production. - `pagamento_em` (string, may be null) — Null for API card purchases. Older checkout records can contain an Asaas HTTPS link. - `criado_em` (string) — Subscription creation time in UTC. - `atualizado_em` (string) — Last change time in UTC. - `cancelamento_em` (string, may be null) — Cancellation request time in UTC, or null. - `cancelado_em` (string, may be null) — Confirmed cancellation time in UTC, or null. - `pago_ate` (string, may be null) — On reads and cancellation, UTC end of the last period with a confirmed, non-refunded invoice; null without a paid invoice. It is not the next charge date or the free trial. ### `OfertaDeAssinatura` - `id` (string) — Offer ID: 2 to 64 characters. Start with a lowercase letter. Use lowercase letters, digits, hyphens or underscores. - `produto` (string) — Product ID, with the same format as the offer ID. - `versao` (int) — Offer version: 1 to 1,000,000. - `preco_centavos` (int) — Price per cycle in cents: 500 to 1,000,000. - `moeda` (string) — Fixed currency: BRL. - `ciclo` (string) — MONTHLY for a monthly offer; WEEKLY for a weekly offer. - `renovacao_automatica` (bool) — true: billing repeats each cycle until cancellation. - `compromisso_meses` (int) — Present only for MONTHLY: one calendar month. - `compromisso_semanas` (int) — Present only for WEEKLY: one seven-day period. - `cancelamento` (string) — stop_future_charges: stop new charges. - `acesso_pago` (string) — until_paid_period_end: keep access until the paid period ends. - `teste_dias` (int) — Configured trial length: 0 to 30 days. Reading the catalog grants no trial or benefit. - `primeira_cobranca` (string, optional) — First charge date in Brasilia (YYYY-MM-DD), selected by the server to preserve the current period. Included in the offer hash and acceptance. - `desconto_primeira_cobranca_centavos` (int, optional) — Deduction in cents for the first invoice only, at most the cycle price. Requires primeira_cobranca and is included in the accepted offer hash. Following cycles keep preco_centavos. - `conversao_teste` (string) — opt_in: a trial does not create or renew a subscription. - `beneficios` (BeneficioDeAssinatura[]) — 1 to 8 distinct capabilities for each paid period. → see `BeneficioDeAssinatura` under **Structures**. - `hash` (string) — SHA-256 of the complete offer: 64 lowercase hexadecimal characters. ### `AceiteDeAssinatura` - `oferta_id` (string) — Offer ID from the current catalog. - `versao` (int) — Offer version from the current catalog. - `hash` (string) — 64-character hash from the current catalog. - `renovacao` (bool) — Must be true after explicit acceptance of the price, cycle and automatic renewal. ### `CartaoDeAssinatura` - `titular` (string) — Name on the card: 3 to 100 characters. - `numero` (string) — Valid card number: 13 to 19 digits. Spaces and separators are accepted. - `mes` (string) — Expiry month: 1 to 12. - `ano` (string) — Four-digit expiry year. The card must not be expired. - `cvv` (string) — Security code: three digits, or four for American Express. - `documento` (string) — Cardholder's valid Brazilian CPF or CNPJ. - `email` (string) — Cardholder's e-mail: at most 254 characters. - `cep` (string) — Cardholder's Brazilian billing postcode: eight digits. - `numero_endereco` (string) — Billing address number: at most 20 characters. - `telefone` (string) — Cardholder's telephone number: 10 to 13 digits. ### `Metricas` 7-day operator dashboard. `payments` only appears with the token and only on Base mainnet. - `app` (string) — Product name. - `today` (string) — Reference day (UTC, YYYY-MM-DD). - `today_visits` (int) — Interface visits counted today. - `today_contacts` (int, optional) — Contact messages today. Only with `METRICS_TOKEN`: contact counts never leave without the token. - `days` (object[]) — One row per day of the window, with each metric's count. - `usage` (object) — `entregas`: deliveries per day — real product usage, not catalog load. - `accounts` (object) — `organizacoes`: total organizations registered. - `financeiro` (object, optional) — Day aggregate: `hoje_usd`, `hoje_count`, `rede`. Only with `METRICS_TOKEN`: money never leaves without the token; the full series is `payments`. - `payments` (object, optional) — x402 and BRL financial summary; METRICS_TOKEN only. - `compras` (object, optional) — Who paid in the last 30 days: up to 20 BRL purchases with name, verified email and use, and the x402 payers by wallet. METRICS_TOKEN only. ### `PaymentFree` - `o_que` (string) — Operation or allowance. - `limite` (string) — Allowance and eligibility. - `janela` (string, may be null) — Reset window, when applicable. ### `PaymentPrice` - `o_que` (string) — Operation and billing unit. - `price_usd` (number, optional) — Current list price in USD. - `price` (string, optional) — Price with its currency or billing unit. - `so_conta` (bool, optional) — Only a signed-in account can buy this offer. ### `PaymentTrial` - `days` (int) — Trial duration in days. - `how` (string) — Eligibility and activation steps. ### `CobrancaDaChamada` The payment of a single call. - `via` (string) — `x402`, `credito` or the marketplace that already charged the call. - `preco_usd` (string) — The price charged for this call in US dollars, such as `0.01`: at least US$ 0.01 with single x402 payment; the unit price with credit. - `repetido` (bool) — `true` when the credit had already paid this request (the same `Idempotency-Key`): nothing was charged again. - `saldo_usd` (string, optional) — The credit balance after the call, such as `$0.99`; includes payment from the account balance. ### `BeneficioDeAssinatura` - `sku` (string) — Product capability: a lowercase letter followed by letters, digits or underscores; at most 64 characters. - `quantidade` (int) — 1 to 1,000,000 units for each paid period. ## Public data archives Browse addresses and procurement by location, then open the records you need. Up to 20 items per page, in formats ready for people and agents. Check coverage and the reference date before using a result. Access options are shown by each product. - [Postal codes and addresses](https://api.pontofato.com/enderecos/index.json): Find addresses by location, with coordinates and a 2022 reference date. Not a current postal-code certification. Each HTML page opens the product app with its public data already rendered. State → municipality → locality → street → addresses. [HTML](https://pontofato.com/enderecos/) · [llms.txt](https://api.pontofato.com/enderecos/llms.txt) · [OKF](https://api.pontofato.com/enderecos/okf/index.md) - [Public procurement](https://api.editalmd.com/licitacoes/index.json): Find public procurement by location and date. View documents and reading options in EditalMD. Each HTML page opens the product app with its public data already rendered. Procedure → state → year → month → day → municipality → purchases. [HTML](https://editalmd.com/licitacoes/) · [llms.txt](https://api.editalmd.com/licitacoes/llms.txt) · [OKF](https://api.editalmd.com/licitacoes/okf/index.md)