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.

Errors

Every non-2xx response uses the same envelope. Agents branch on error.type (a stable 10-value enum); each error carries nextActions[] — concrete steps to surface to the user.

Envelope shape

{
  "error": {
    "type": "rate_limited",
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded (rpm_exceeded). Retry after 23s.",
    "doc": "https://docs.mareaalcalina.com/concepts/rate-limits",
    "param": null,
    "requestId": "req_30a9358b-70bd-44f3-aa5d-8983b558ad84",
    "requestLogUrl": "https://...",
    "recoverable": true,
    "retryAfterMs": 23000,
    "nextActions": [
      { "label": "Wait 23s and retry the same request.", "method": null, "url": null }
    ],
    "upgrade": null
  }
}

Field guarantees

FieldTypeNotes
typeenum (10 values)Stable. Agents branch on this. See the table below.
codestringStable, machine-readable. Finer-grained than type.
messagestringHuman-readable. Localized via Accept-Language. Do not branch on it.
docstringLink to the relevant docs page for this code.
paramstring | nullName of the offending field (null if not field-specific). Never missing.
requestIdstringreq_<uuid> — surface to the user when reporting bugs.
requestLogUrlstringInternal log URL (operator-only).
recoverablebooleantrue means a retry is meaningful (with appropriate changes).
retryAfterMsinteger | nullWhen set, also returned as the Retry-After header (in seconds).
nextActionsarrayAlways an array (possibly empty). null is not allowed. Each entry: { label, method, url }.
upgradeobject | null{ currentPlan, requiredPlan, upgradeUrl, previewUrl? }. Set only on plan_limit errors.
requiredScopesstring[] (optional)Present only when the failure is a scope mismatch.
heldScopesstring[] (optional)Present only when the failure is a scope mismatch.

The 10 error types

typeTypical HTTPWhen it happensAgent action
rate_limited429rpm or rpd quota exceededRead retryAfterMs, sleep, retry. recoverable: true. See Rate limits.
invalid_request400 / 410 / 422Malformed body, invalid Idempotency-Key, oversize snapshot, empty publishFix the body and reissue. Do not retry the exact same request.
auth401 / 403Missing / invalid / revoked key, missing scope401 → fix credential. 403 with requiredScopes → request an upscoped key.
not_found404Resource missing OR cross-tenant access (silent denial)Confirm the id is correct AND the key owns it.
plan_limit402Plan ceiling hit (publish blocked, product cap exceeded)Surface upgrade.upgradeUrl to the user as a CTA. See Plan limits.
internal500Server bugSurface requestId. Retry once with backoff, then escalate.
conflict409Idempotency-Key in flight (same key still processing)Wait retryAfterMs and retry with the same key.
idempotency_conflict409Same Idempotency-Key reused with a different bodyGenerate a NEW Idempotency-Key. See Safe mutations.
service_unavailable503Dependency outage or feature flag offRetry with exponential backoff.
tos_not_accepted451Calling user has not accepted the Terms of ServiceSurface nextActions[0] (dashboard link). User must accept; agent cannot bypass. See ToS jurisdiction.

Recovery matrix

If error.type isSurface to user?Retry?What to do
rate_limitedNo (transparent)Yes after retryAfterMsSleep + retry same request + same Idempotency-Key
invalid_requestNo (fix client-side)No (without fixing)Fix the body. Do not retry blindly.
auth (401)Maybe (credential issue)NoRe-prompt for a valid key
auth (403, scope)MaybeNoRequest a key with requiredScopes
not_foundMaybe (“not found”)NoConfirm id; confirm key ownership
plan_limitYes (paywall CTA)NoSurface upgrade.upgradeUrl verbatim
internalYes (with requestId)Once with backoffThen escalate
conflict (in-flight idempotency)NoYes after 1sRetry with same Idempotency-Key
idempotency_conflictNoYes with NEW keyGenerate a fresh Idempotency-Key
service_unavailableYes (after retries)Yes with backoffExponential backoff
tos_not_acceptedYes (ToS link)After user acceptsSurface nextActions[0].url

Stable code reference

Every code below is emitted by production code today. Agents may branch on code for finer-grained handling than type.

Auth (401 / 403)

codeHTTPSource
missing_authorization401src/api/middleware/apiKey.ts
invalid_authorization_format401src/api/middleware/apiKey.ts
key_not_found401src/api/middleware/apiKey.ts
key_revoked401src/api/middleware/apiKey.ts
insufficient_scope403src/api/middleware/scope.ts — includes requiredScopes/heldScopes
developer_context_unresolved401Bootstrap / issue-key handlers when developer ctx is missing
tenant_unresolved401Catalog / verify handlers when owner ctx is missing
developer_not_found404src/api/v1/me.get.ts — dev account missing from Firebase Auth

Validation (400 / 410 / 413 / 422)

codeHTTPSource
invalid_request400Zod validation failure (per-field)
invalid_json400Body parsing failure
invalid_idempotency_key400src/api/middleware/idempotency.ts
invalid_storefront_id400src/api/services/translation/storefront-id.ts
invalid_product_id400src/api/services/translation/storefront-id.ts
invalid_email_syntax400Bootstrap email validation
invalid_email_mx400Bootstrap MX-record check
code_invalid400src/api/v1/users.verify.ts
code_expired410src/api/v1/users.verify.ts
idempotency_snapshot_unavailable410src/api/middleware/idempotency.ts (oversize replay)
payload_too_large413Body parser
no_products422src/api/v1/storefronts.publish.ts (empty storefront)
user_not_verified422src/api/v1/users.issueKey.ts (pre-verify additional key)
blocks_explicit_not_supported422Storefront manifest (legacy block fields)
theme_preset_not_supported422Storefront manifest (theme presets not on plan)

Not found (404)

codeHTTPSource
storefront_not_found404src/api/v1/storefronts.* — also fires on cross-tenant access
user_not_found404Verify, resend, issue-key handlers — also cross-tenant
code_not_found404src/api/v1/users.verify.ts — no active verification code

Conflicts (409)

codeHTTPSource
idempotency_in_flight409src/api/middleware/idempotency.ts — emits Retry-After: 1
idempotency_conflict409src/api/middleware/idempotency.ts — different body, same key
email_exists409Bootstrap — email already registered

Plan / paywall (402)

codeHTTPSource
plan_blocks_publish402src/api/v1/storefronts.publish.ts (NO_ACTIVO plan)
plan_max_products_reached402src/services/catalog/productCreateCore.ts — single-product POST would exceed the plan cap
plan_max_storefronts_reached402src/api/v1/storefronts.create.ts — would exceed the per-plan storefront cap
plan_limit_exceeded402src/api/middleware/planLimits.ts — generic plan-cap rejection at middleware layer
products_over_limit207/402src/api/v1/storefronts.create.ts (manifest with too many products) — 207 partial OR 402 over cap

Rate limit (429)

codeHTTPSource
rate_limit_exceeded429src/api/middleware/rateLimit.tsrpm_exceeded / rpd_exceeded
too_many_attempts429src/api/v1/users.verify.ts — 3 wrong codes
bootstrap_ip_rate_limited429src/api/services/bootstrap.service.ts
bootstrap_quota_exhausted429src/api/services/bootstrap.service.ts
resend_hour_limit429src/api/v1/users.resendVerification.ts
resend_day_limit429src/api/v1/users.resendVerification.ts

ToS (451)

codeHTTPSource
tos_required451Reserved on storefronts.publish — see ToS jurisdiction

Service / internal (500 / 503)

codeHTTPSource
api_disabled503src/api/middleware/featureFlag.ts — kill switch
verify_unexpected_state500src/api/v1/users.verify.ts — defense-in-depth fall-through
internal_error500Unhandled exception path

What NOT to do

  • Do not branch on error.message — it’s localized via Accept-Language and may change. Branch on error.type (enum) and error.code (string).
  • Do not swallow nextActions[]. The most common agent-failure mode is silently retrying past a 402 (paywall) or 451 (ToS) without ever showing the user the action.
  • Do not auto-accept the ToS on the user’s behalf. The 451 → modal flow requires user input by design.
  • Do not retry invalid_request with the same body. Fix the body first.
  • Do not branch on HTTP status alone. Several types share a status (409 for two conflict shapes; 404 for both real-missing and cross-tenant). The type + code pair disambiguates.

Verification in code

  • src/api/contracts/error.zod.ts — the locked envelope schema (10 type values).
  • src/api/api-error.ts — the ApiError class that wires status + type + code + recovery hints.
  • src/api/middleware/errors.ts — the global error handler that emits the envelope.