API keys
Almost every integration with Marea uses one kind of key: amk_user_* issued to a single Marea user, used to manage all of that user’s storefronts and products.
A second kind — mk_dev_* — exists for a separate class of caller: agents, vertical-SaaS, and agencies that create Marea accounts on behalf of other people. Most readers will never need one.
^mk_(dev|user)_[A-Za-z0-9]+$. The random suffix is 24 base62 chars (~143 bits of entropy).
The default: mk_user_* (user-key)
A user-key represents one specific Marea user and is the credential you use for everything that happens inside that user’s account.
One key covers ALL of that user’s storefronts. A user-key is owner-scoped, not storefront-scoped. The same
mk_user_* can GET / POST / PATCH / publish against every storefront the user owns — whether that’s 1 (Free plan) or 5,000 (Agency Growth plan). You do not issue a separate key per storefront. You do not pass a Storefront-Id header — the storefront is in the URL path; the key proves you own it.
How to get one:
- If you signed up at mareaalcalina.com and own a storefront, mint a
mk_user_*in one click from your dashboard at/developers/keys. - If you were bootstrapped through a partner integration, you received your
mk_user_*in thePOST /v1/usersresponse — store it then.
GET /v1/me— confirm identity, read your plan + limitsGET /v1/storefronts,POST /v1/storefronts,PATCH /v1/storefronts/:id— manage your storefrontsPOST .../products,PATCH .../products/:id,GET .../products— manage your catalogPOST .../publish— take a storefront live (gated by ToS + plan)- (after Phase B)
POST /v1/webhook_endpoints— receiveorder.*events from your store
- Bootstrap other users (that requires
developer:bootstrap, held only bymk_dev_*) - See or edit anyone else’s data — tenant boundary is encoded in the key itself
Pre-verify vs post-verify scopes
If yourmk_user_* came from a fresh POST /v1/users (partner bootstrap), it starts with a restricted scope set — me:verify, me:resendVerification, catalog:read. The only mutating calls it can make are verify and resend.
When the user submits the 6-digit code (POST /v1/users/:userId/verify), the same key is upgraded in place to catalog:read, catalog:write, storefront:publish. No rotation — store the value once at bootstrap time.
User-keys minted from the dashboard (self-issued by an already-verified user) start in the full post-verify state.
Keys created by AI connections
There is a third way amk_user_* comes into existence: you connect Marea to an AI client over MCP. When you press Autorizar on the consent screen, Marea mints a key for that connection and names it after the app and its domain, for example Claude · claude.ai or ChatGPT · chatgpt.com. You never see it or paste it. The OAuth token the client holds resolves to that key on every call, so the REST API sees an ordinary per-user key with your usual scopes.
Two things follow from that:
- The key is yours to delete. It is listed in your dashboard under Desarrolladores, Claves API, next to the keys you minted yourself. Delete it and the app is disconnected: its next call comes back 401, the OAuth grant behind it is dropped, and the client has to send you through sign-in again if you want it back.
- It is a per-user key, with the limits of one. No OAuth connection can bootstrap accounts for other people, whatever scopes were granted, because
developer:bootstrapis held only bymk_dev_*.
POST /oauth/revoke on the MCP server) ends the OAuth grant but leaves the key in place. Deleting the key is the action that works from Marea’s side alone, without touching the app. See Connect Marea to your AI client.
The advanced case: mk_dev_* (partner / developer key)
A mk_dev_* is for callers that act on behalf of many users — three real archetypes:
- AI agents (Claude, ChatGPT, Cursor) that bootstrap Marea accounts as part of helping their own end-users.
- Vertical SaaS (e.g., a LATAM restaurant-management product) embedding Marea so their customers get a storefront without the SaaS building one.
- Agencies running marketing for many small clients — one operator console, many client storefronts.
How to get one: Issue from the developer dashboard at mareaalcalina.com/developers/keys. The raw value is shown once; server-side only the SHA-256 hash is stored.
What you can do with it:
POST /v1/users— bootstrap a new Marea user (returns theirmk_user_*in the response)GET /v1/users,GET /v1/users/:userId— list / inspect users you’ve bootstrappedPOST /v1/users/:userId/keys— mint an additionalmk_user_*for a user you’ve bootstrapped (e.g., a second integration)- All
/v1/webhook_endpoints/*operations — manage your webhook endpoints (user.*lifecycle on accounts you bootstrapped +order.*from those accounts’ storefronts)
- Touch any user’s catalog directly. To edit a user’s storefront, use the
mk_user_*you got back from their bootstrap. Even a partner who owns a Marea storefront themselves uses their ownmk_user_*for that storefront — the dev-key never grants catalog access.
mk_dev_* can bootstrap new fake accounts and read user metadata, but can’t rewrite a single user’s prices.
Authenticating
Pass the key inAuthorization: Bearer <key> (preferred). X-API-Key: <key> is accepted as a fallback. Any other header — or a non-Bearer Authorization scheme — fails with invalid_authorization_format.
Scopes table
Scope checks run after key lookup. Endpoints declare a required scope set; the auth layer supports bothany (one-of) and all (require-all) semantics.
GET /v1/me accepts any of the user scopes; developer keys bypass the scope check entirely (a developer key always sees its own identity).
Scope mismatch (403)
requiredScopes and heldScopes verbatim — the diff between them tells you exactly which kind of key you should have used (mk_user_* for catalog scopes; mk_dev_* for developer scopes).
Rotation
There is norotate call. To rotate:
- Revoke the old key.
- Issue a new one (developer dashboard for
mk_dev_*; user dashboard formk_user_*; orPOST /v1/users/:userId/keyswith a developer key for an additional user-key on a bootstrapped user). - Update your client.
Revocation
Revoked keys stop authenticating within ~60s end-to-end (the negative-lookup cache TTL). After revocation:- The key returns
401 key_revokedon every request. - Webhook endpoints are NOT tied to a single key — they belong to your account and survive key revocation. Revoking a single key does not delete or disable any endpoint. See Webhook endpoints for the lifecycle.
- Revocation is non-cascading: revoking a developer key does NOT revoke the user keys it minted. To wipe everything for an owner, the owner-scoped revoke-all path is used (operator path; not in the public API).
Auth errors (401)
All four are 401 with
recoverable: false. Don’t loop — fix the credential.