Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mareaalcalina.com/llms.txt

Use this file to discover all available pages before exploring further.

AGENTS.md — Marea Alcalina API

Following the agents.md spec. This file is for AI agents (Claude, GPT, Cursor, Continue.dev, generic LLM-driven tools) consuming the Marea public API. For the full doc index in agent-friendly markdown form, fetch llms.txt.

What this API is for

Operations + retention API for small-business commerce. Bootstrap users, manage storefronts + products (food menus or retail / service catalogs), publish to public hosted URLs. End-customer order channels are the operator’s choice — WhatsApp, web checkout, or in-person pickup — and configurable per storefront. The API does not lock the channel.

Auth model

Two-tier (see Two-tier keys for the full model):
  • mk_dev_*developer key, held by the agent or app builder. Holds developer:bootstrap, developer:read, developer:issueUserKey. Default rpd: 50 (configurable at issue time; the dev rpd IS the bootstrap cap, not a separate quota).
  • mk_user_*per-user key, returned by POST /v1/users and scoped to one user. Issued restricted (only me:verify + me:resendVerification) until the 6-digit code is verified, then upgraded in-place to full catalog scopes (catalog:read, catalog:write, storefront:publish). Cannot bootstrap, cannot see other users’ data.
Both pass as Authorization: Bearer <key> (or X-API-Key: <key> as a fallback). The split lets an agent bootstrap users with its own dev key and receive a per-user key in the response — the agent never holds the user’s password.

Common patterns

  • Bootstrap → verify → use. POST /v1/users returns a restricted mk_user_* key + emails the user a 6-digit code. The user reads the code aloud (or the agent fetches it via Gmail-MCP), agent calls POST /v1/users/:userId/verify, the same key is upgraded to full per-user scope. See Bootstrap quickstart.
  • Idempotency on every mutation. Pass Idempotency-Key: <uuid-v4> on every POST and PATCH. Same key + same body returns the original response (replay-safe). Same key + different body returns 409 idempotency_conflict. See Safe mutations.
  • Branch on error.type, not error.message. The type field is a stable 10-value enum; message is localized and may change. See Errors.
  • Surface nextActions[] verbatim. Every error returns { label, method, url }[] — these are the concrete actions the user can take. Don’t paraphrase; render verbatim.
  • Read rate-limit headers proactively. X-RateLimit-Remaining is on every response. When you hit 429, read Retry-After (seconds) and back off. Defaults: rpm: 60. Dev keys: rpd: 50. User keys: rpd: 10000.
  • Markdown for ingestion. Every doc page also serves at <page>.md (e.g., /concepts/errors.md); use that variant when ingesting docs into your context — cleaner than the HTML.

When to call which tool

REST (always available) and MCP tool (when the user has installed the Marea MCP server in Claude Desktop / Cursor / Continue.dev — see MCP install quickstart).
GoalRESTMCP tool
Bootstrap a new userPOST /v1/users (dev key)marea.bootstrap_user
Verify the 6-digit email codePOST /v1/users/:userId/verify(use REST in v1)
Read identity / plan / budgetGET /v1/memarea.whoami
Create a storefrontPOST /v1/storefrontsmarea.create_storefront
Update storefront fieldsPATCH /v1/storefronts/:idmarea.update_storefront
Add a productPOST /v1/storefronts/:id/productsmarea.create_product
Update a productPATCH /v1/storefronts/:id/products/:productIdmarea.update_product
Publish to public URL (needs user confirmation)POST /v1/storefronts/:id/publishmarea.publish_storefront (fires MCP elicitation)
Prefer the MCP tool when the user has the MCP server installed — it gives the user explicit confirmation prompts via MCP elicitation primitives. Fall back to REST when MCP isn’t available.

What NOT to do

  • Don’t swallow nextActions[]. The most common agent failure mode is silently retrying past a 402 (paywall) or 451 (ToS not accepted) without ever surfacing the action to the user. Render the array verbatim.
  • Don’t auto-accept the ToS on the user’s behalf. A 451 → modal flow requires user input by design. The agent cannot bypass.
  • Don’t bootstrap past your dev key’s rpd cap. Default is 50/day (configurable at issue time). Hitting it returns 429 rate_limited with code: rate_limit_exceeded and rpd_exceeded in error.message. Read Retry-After (seconds-until-the-day-rolls-over) and back off.
  • Don’t call publish without explicit user confirmation. Publish is destructive and user-visible. Use MCP elicitation if you have the MCP tool; otherwise prompt the user explicitly.
  • Don’t cache mk_user_* keys across users or sessions. Per-user keys belong in the user’s own context.
  • Don’t poll verification status faster than the API allows. The user-facing rate limit is rpm: 60 per user-key. Poll at most once every 30s during the verify window; better, subscribe to the user.verified agent webhook on the developer key — see Agent webhooks.
  • Don’t reuse the same Idempotency-Key with a different body. That returns 409 idempotency_conflict and you must generate a fresh key. If you’re retrying with edits, that’s a new request — new key.
  • Don’t branch on the localized error.message. Branch on error.type (stable enum) or error.code (stable string).

Errors

Every error follows the same envelope: { type, code, message, doc, requestId, recoverable, retryAfterMs, nextActions, upgrade, requiredScopes? }. Branch on error.type. The 10 stable types:
error.typeTypical HTTPSurface to user?Retry?What to do
rate_limited429No (transparent)Yes after retryAfterMsSleep + retry same request + same Idempotency-Key
invalid_request400 / 410No (fix client-side)NoFix the body. Includes invalid_idempotency_key, idempotency_snapshot_unavailable
auth (401)401MaybeNoRe-prompt for a valid key. Codes: missing_authorization, invalid_authorization_format, key_not_found, key_revoked
auth (insufficient scope)403MaybeNoRead requiredScopes + heldScopes arrays; ask user/dev for a key with the right scope
not_found404MaybeNoConfirm the id. May also be a silent cross-tenant denial if the calling key doesn’t own the resource
plan_limit402Yes (paywall)NoSurface error.upgrade.upgradeUrl verbatim. The user must upgrade, then retry
internal500Yes (with requestId)Once with backoffThen escalate. Surface requestId so support can trace
conflict409NoYes after 1sidempotency_in_flight — the same key is still processing. Retry with same key
idempotency_conflict409NoYes with new Idempotency-KeySame key was used earlier with a different body. Generate a fresh UUID
service_unavailable503Yes (after retries)Yes with backoffExponential backoff
tos_not_accepted451Yes (link to dashboard)After user acceptsSurface nextActions[0].url (modal). Agent cannot bypass
Full error matrix at /concepts/errors.

Where to find docs

Conventions

  • Locale: Accept-Language is honored. Default es-MX. Pass Accept-Language: en for English error messages, pt for Portuguese.
  • Currency: configurable per storefront. Pass currency: "MXN" | "USD" | "CAD" | "BRL" | ... on storefront create.
  • Phone format: E.164 (+52...).
  • Timestamps: ISO 8601 strings.
  • IDs: prefixed (usr_, stf_, prd_, dev_).