Skip to main content

API keys

Almost every integration with Marea uses one kind of key: a mk_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.
Format is locked: ^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 the POST /v1/users response — store it then.
What you can do with it:
  • GET /v1/me — confirm identity, read your plan + limits
  • GET /v1/storefronts, POST /v1/storefronts, PATCH /v1/storefronts/:id — manage your storefronts
  • POST .../products, PATCH .../products/:id, GET .../products — manage your catalog
  • POST .../publish — take a storefront live (gated by ToS + plan)
  • (after Phase B) POST /v1/webhook_endpoints — receive order.* events from your store
What you can’t do:
  • Bootstrap other users (that requires developer:bootstrap, held only by mk_dev_*)
  • See or edit anyone else’s data — tenant boundary is encoded in the key itself

Pre-verify vs post-verify scopes

If your mk_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 a mk_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:bootstrap is held only by mk_dev_*.
Revoking the token from the app side (its connector settings, or 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:
  1. AI agents (Claude, ChatGPT, Cursor) that bootstrap Marea accounts as part of helping their own end-users.
  2. Vertical SaaS (e.g., a LATAM restaurant-management product) embedding Marea so their customers get a storefront without the SaaS building one.
  3. Agencies running marketing for many small clients — one operator console, many client storefronts.
If none of those describe you, skip this section. 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 their mk_user_* in the response)
  • GET /v1/users, GET /v1/users/:userId — list / inspect users you’ve bootstrapped
  • POST /v1/users/:userId/keys — mint an additional mk_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)
What you can’t do:
  • 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 own mk_user_* for that storefront — the dev-key never grants catalog access.
The split is a security boundary: a leaked mk_dev_* can bootstrap new fake accounts and read user metadata, but can’t rewrite a single user’s prices.

Authenticating

Pass the key in Authorization: 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 both any (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)

Surface 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 no rotate call. To rotate:
  1. Revoke the old key.
  2. Issue a new one (developer dashboard for mk_dev_*; user dashboard for mk_user_*; or POST /v1/users/:userId/keys with a developer key for an additional user-key on a bootstrapped user).
  3. 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_revoked on 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.