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.

Publish a storefront

Publish is the one operation that takes a storefront from draft to public — the URL becomes shareable, indexable, and live for end customers. Required scope: storefront:publish. Always require explicit user confirmation before calling — publish is user-visible.

Pre-flight checklist

Before calling publish:
  1. The storefront must have at least one product (else 422 no_products).
  2. The user must be on any active plan — Free, Basic, Pro, Business, or Agency. Pre-paywall accounts (just-signed-up, no plan picked) get 402.
  3. The user must have accepted the dashboard ToS modal (else 451). The agent cannot bypass this.
Short-circuit with GET /v1/me if you want to surface a CTA before the publish round-trip:
{
  "plan": { "tier": "free", "limits": { "publishable": true, "products": 30, "storefronts": 1 } },
  "tosAcceptedAt": "2026-04-15T10:23:00Z"
}
If plan.limits.publishable is false or tosAcceptedAt is null, surface the appropriate next-action to the user before attempting publish.

Request

POST /v1/storefronts/{storefrontId}/publish — body is optional.
curl -X POST https://api.mareaalcalina.com/v1/storefronts/stf_9a8b7c6d/publish \
  -H "Authorization: Bearer mk_user_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 2f1a8c4b-2e3a-4b9d-9f1a-8c4b2e3a4b9d" \
  -d '{}'
Send { "versionId": "ver_xxx" } to publish a specific version snapshot; omit for auto-version (the common case — Marea creates a fresh snapshot from the current draft).

200 OK — success

{
  "storefront": {
    "id": "stf_9a8b7c6d5e4f3a2b1c0d9e8f",
    "name": "Tacos La Marea",
    "language": "es",
    "currency": "MXN",
    "businessType": "restaurant",
    "published": true,
    "publishedDate": "2026-05-10T18:30:00.000Z",
    "_links": {
      "previewUrl": "https://marea.pro/preview/pv_8c4b2e3a4b9d",
      "publicUrl": "https://marea.pro/tacos-la-marea",
      "editUrl": "https://mareaalcalina.com/dashboard/menu/stf_9a8b7c6d5e4f3a2b1c0d9e8f"
    }
  }
}
Surface _links.publicUrl to the user — that’s the share-and-print-and-QR-code URL.

The four error gates

Every error follows the §9.6 envelope verbatim. Branch on error.type + error.code; surface nextActions[] to the user without paraphrasing.

402 — plan paywall (plan_blocks_publish)

The user is pre-paywall (no plan picked yet). Surface error.upgrade.upgradeUrl as a CTA; do not retry until the user upgrades.
{
  "error": {
    "type": "plan_limit",
    "code": "plan_blocks_publish",
    "message": "Your plan does not permit publishing. Upgrade to publish this storefront.",
    "doc": "https://docs.mareaalcalina.com/concepts/plan-limits#publish-paywall",
    "param": null,
    "requestId": "req_30a9358b-70bd-44f3-aa5d-8983b558ad84",
    "requestLogUrl": "https://mareaalcalina.com/developers/logs/req_30a9358b-70bd-44f3-aa5d-8983b558ad84",
    "recoverable": true,
    "retryAfterMs": null,
    "nextActions": [
      { "label": "Pick a plan to publish.", "method": null, "url": "https://mareaalcalina.com/upgrade?planSource=api" }
    ],
    "upgrade": {
      "currentPlan": "free",
      "requiredPlan": "basic",
      "upgradeUrl": "https://mareaalcalina.com/upgrade?planSource=api"
    }
  }
}

422 — empty storefront (no_products)

The storefront has 0 products. Use nextActions[0].url to add a product before retrying.
{
  "error": {
    "type": "invalid_request",
    "code": "no_products",
    "message": "Cannot publish an empty storefront. Add at least one product first.",
    "doc": "https://docs.mareaalcalina.com/concepts/publishing#no-products",
    "param": null,
    "requestId": "req_30a9358b-70bd-44f3-aa5d-8983b558ad84",
    "requestLogUrl": "https://mareaalcalina.com/developers/logs/req_30a9358b-70bd-44f3-aa5d-8983b558ad84",
    "recoverable": true,
    "retryAfterMs": null,
    "nextActions": [
      { "label": "Add at least one product before publishing.", "method": "POST", "url": "/v1/storefronts/stf_9a8b7c6d5e4f3a2b1c0d9e8f/products" }
    ],
    "upgrade": null
  }
}

451 — ToS not accepted (tos_required)

The user hasn’t accepted the dashboard ToS modal. The agent cannot bypass — the user must complete the modal in their browser. Retry with the same Idempotency-Key after the user accepts.
{
  "error": {
    "type": "tos_not_accepted",
    "code": "tos_required",
    "message": "The account holder must accept the Marea Terms of Service before this storefront can be published.",
    "doc": "https://docs.mareaalcalina.com/concepts/tos-jurisdiction",
    "param": null,
    "requestId": "req_30a9358b-70bd-44f3-aa5d-8983b558ad84",
    "requestLogUrl": "https://mareaalcalina.com/developers/logs/req_30a9358b-70bd-44f3-aa5d-8983b558ad84",
    "recoverable": true,
    "retryAfterMs": null,
    "nextActions": [
      { "label": "Open the dashboard so the user can accept the Terms of Service.", "method": "GET", "url": "https://mareaalcalina.com/dashboard/tos" }
    ],
    "upgrade": null
  }
}

404 — not found (storefront_not_found)

Wrong storefrontId, or this user-key doesn’t own it. Cross-tenant returns 404 (leak-less), not 403 — you cannot infer existence.

Summary table

HTTPerror.type / codeWhyWhat to do
402plan_limit / plan_blocks_publishPre-paywall accountSurface error.upgrade.upgradeUrl; do not retry until upgrade.
422invalid_request / no_products0 productsUse error.nextActions[0] (POST products URL), then retry.
451tos_not_accepted / tos_requiredToS modal not completedSurface nextActions[0].url (dashboard). Agent cannot bypass. Retry with same Idempotency-Key after user accepts.
404not_found / storefront_not_foundWrong id or cross-tenantConfirm id + ownership; cannot retry blindly.
429rate_limited / rpm_exceededPer-user rpm: 60 capSleep Retry-After, retry with same key.

Idempotent republishing

Calling publish on an already-published storefront with the same versionId is a no-op that returns 200 with the same DTO. To republish a new version, omit versionId (auto-version) — Marea creates a fresh snapshot, runs the publish, and the live URL points at the new content. You can keep the same Idempotency-Key across retries of the same publish attempt; generate a fresh key for a new republish.

Cross-references