Skip to main content

Bootstrap a user account

This is the partner / agent flow. Use it when you’re building an AI agent, vertical SaaS, or agency tool that creates Marea accounts for other people. If you already own a Marea storefront and just want API access to it, you don’t need this — grab your mk_user_* from your dashboard and skip straight to Add products.
One call creates the user, a starter storefront, and a per-user API key. Marea also emails a 6-digit code to the user; a follow-up call verifies it and unlocks catalog writes. You never touch the user’s password. The whole flow is two HTTP calls.

Step 1 — Create the user

Response — 201 Created:
userKey is shown once. Store it now — there’s no way to read it back. Treat it like a password.
From here on, every catalog call uses $MAREA_USER_KEY. You only reach back for $MAREA_DEV_KEY when bootstrapping another user, listing your users, or managing webhook endpoints.

Required body fields

Partial-success (207)

If initialStorefront.products[] exceeds the user’s plan cap, Marea returns 207 with the storefront created up to the cap and an errors[] array describing what was skipped. Surface those verbatim and prompt for upgrade. See Plan limits.

Step 2 — Verify the 6-digit code

The user gets a code in their inbox. Either ask them to read it aloud, or read it via the Gmail MCP — see Verification flow.
Response — 200 OK:
The same $MAREA_USER_KEY is now upgraded in place — it gains catalog:read, catalog:write, storefront:publish on top of the verify scopes it already had. Do not rotate or re-issue. You can now call any product or storefront endpoint.

If the code is wrong / expired / never arrived

Two keys, one mental model

You only see two API keys in the whole API:
  • $MAREA_DEV_KEY — your agent’s own key, issued from /developers/keys. Used to bootstrap users and manage webhook endpoints. Never grants catalog access.
  • $MAREA_USER_KEY — a single user’s key, returned by POST /v1/users. Used for everything you do on behalf of that user (catalog reads, product writes, publish) across every storefront the user owns. One key per user, not one key per storefront. Tenant boundary is baked into the key — it can only see/edit that user’s data.
If you hit 403 insufficient_scope, you’re sending the wrong key. The error response includes requiredScopes[] and heldScopes[] so you can tell at a glance which one was needed. Full model + rotation rules: /concepts/keys.

Errors you should branch on

Every non-2xx follows the §9.6 envelope: { type, code, message, doc, param, requestId, requestLogUrl, recoverable, retryAfterMs, nextActions[], upgrade }. Branch on error.type and error.code — never on error.message (localized).

Step 1 — POST /v1/users

Step 2 — POST /v1/users/:userId/verify

Full error matrix at /concepts/errors. Idempotency rules at /concepts/safe-mutations. Rate-limit defaults at /concepts/rate-limits.

Next steps