{"openapi":"3.1.0","info":{"title":"Marea Alcalina API","version":"1.0.0"},"servers":[{"url":"https://api.mareaalcalina.com"}],"components":{"schemas":{"ApiNextAction":{"type":"object","properties":{"label":{"type":"string","example":"Validate the JSON before retrying."},"method":{"type":["string","null"],"example":null},"url":{"type":["string","null"],"example":null}},"required":["label","method","url"],"description":"A concrete action the agent can offer the user."},"ApiErrorUpgrade":{"type":["object","null"],"properties":{"currentPlan":{"type":"string","example":"free"},"requiredPlan":{"type":"string","example":"pro"},"upgradeUrl":{"type":"string","example":"https://mareaalcalina.com/upgrade?planSource=api"},"previewUrl":{"type":"string","description":"Optional preview link the agent can surface."}},"required":["currentPlan","requiredPlan","upgradeUrl"]},"ApiErrorBody":{"type":"object","properties":{"type":{"type":"string","enum":["rate_limited","invalid_request","auth","not_found","plan_limit","internal","conflict","idempotency_conflict","service_unavailable","tos_not_accepted"],"description":"High-level error category. Agents branch on this.","example":"auth"},"code":{"type":"string","description":"Stable machine-readable code.","example":"missing_authorization"},"message":{"type":"string","description":"Human-readable, localized via Accept-Language."},"doc":{"type":"string","description":"Link to docs for this error code."},"param":{"type":["string","null"]},"requestId":{"type":"string","example":"req_30a9358b-70bd-44f3-aa5d-8983b558ad84"},"requestLogUrl":{"type":"string"},"recoverable":{"type":"boolean"},"retryAfterMs":{"type":["integer","null"]},"nextActions":{"type":"array","items":{"$ref":"#/components/schemas/ApiNextAction"}},"upgrade":{"$ref":"#/components/schemas/ApiErrorUpgrade"},"requiredScopes":{"type":"array","items":{"type":"string"}},"heldScopes":{"type":"array","items":{"type":"string"}}},"required":["type","code","message","doc","param","requestId","requestLogUrl","recoverable","retryAfterMs","nextActions","upgrade"]},"ApiErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ApiErrorBody"}},"required":["error"],"description":"§9.6 uniform error envelope. Every non-2xx response uses this shape."},"MePlanLimits":{"type":"object","properties":{"storefronts":{"type":"integer","minimum":0},"products":{"type":"integer","minimum":0},"publishable":{"type":"boolean"}},"required":["storefronts","products","publishable"]},"MePlan":{"type":["object","null"],"properties":{"tier":{"type":"string","enum":["free","basic","pro","business"],"description":"Plan tier the calling user is on. Numeric internal plans map to one of these 4.","example":"free"},"limits":{"$ref":"#/components/schemas/MePlanLimits"}},"required":["tier","limits"]},"MeRateLimit":{"type":"object","properties":{"rpm":{"type":"integer","exclusiveMinimum":0,"example":60},"rpd":{"type":"integer","exclusiveMinimum":0,"example":10000},"remainingMinute":{"type":"integer","minimum":0},"remainingDay":{"type":"integer","minimum":0}},"required":["rpm","rpd","remainingMinute","remainingDay"]},"MeLinks":{"type":"object","properties":{"upgradeUrl":{"type":["string","null"]},"dashboardUrl":{"type":["string","null"]},"developerDashboardUrl":{"type":["string","null"]}}},"MeResponse":{"type":"object","properties":{"id":{"type":"string","example":"usr_abc123"},"type":{"type":"string","enum":["user","developer"]},"email":{"type":"string"},"displayName":{"type":"string"},"verificationStatus":{"type":["string","null"],"enum":["pending","verified"]},"tosAcceptedAt":{"type":["string","null"]},"plan":{"$ref":"#/components/schemas/MePlan"},"planQuantity":{"type":["integer","null"],"exclusiveMinimum":0},"rateLimit":{"$ref":"#/components/schemas/MeRateLimit"},"keyId":{"type":["string","null"]},"_links":{"$ref":"#/components/schemas/MeLinks"}},"required":["id","type","email","displayName","rateLimit","keyId","_links"],"description":"Identity + plan info for the calling key. Available to both user and developer keys (branched by `type`)."},"StorefrontLinks":{"type":"object","properties":{"editUrl":{"type":["string","null"]},"publicUrl":{"type":["string","null"]}},"required":["editUrl","publicUrl"]},"StorefrontDto":{"type":"object","properties":{"id":{"type":"string","pattern":"^stf_","example":"stf_abc123"},"name":{"type":"string"},"language":{"type":"string","enum":["es","en","pt"]},"currency":{"type":"string"},"businessType":{"type":["string","null"]},"branding":{"type":["object","null"],"properties":{"logoUrl":{"type":["string","null"]},"backgroundUrl":{"type":["string","null"]},"theme":{"type":["object","null"],"properties":{"primary":{"type":["string","null"]},"secondary":{"type":["string","null"]},"tertiary":{"type":["string","null"]}},"required":["primary","secondary","tertiary"]},"font":{"type":["string","null"]}},"required":["logoUrl","backgroundUrl","theme","font"]},"schedule":{"type":["object","null"],"properties":{"monday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"tuesday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"wednesday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"thursday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"friday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"saturday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"sunday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]}},"required":["monday","tuesday","wednesday","thursday","friday","saturday","sunday"]},"delivery":{"type":["object","null"],"properties":{"enabled":{"type":"boolean"},"type":{"type":["string","null"],"enum":["fixed","distance"]},"fixedPrice":{"type":["number","null"]},"ranges":{"type":["array","null"],"items":{"type":"object","properties":{"fromKm":{"type":"number"},"toKm":{"type":["number","null"]},"price":{"type":"number"}},"required":["fromKm","toKm","price"]}}},"required":["enabled","type","fixedPrice","ranges"]},"pickup":{"type":["boolean","null"]},"dineIn":{"type":["boolean","null"]},"whatsapp":{"type":["string","null"]},"biography":{"type":["object","null"],"properties":{"title":{"type":"string"},"description":{"type":"string"}},"required":["title","description"]},"categories":{"type":["array","null"],"items":{"type":"object","properties":{"name":{"type":"string"},"position":{"type":["integer","null"]}},"required":["name","position"]}},"slug":{"type":["string","null"]},"hidden":{"type":["boolean","null"]},"published":{"type":["boolean","null"]},"_links":{"$ref":"#/components/schemas/StorefrontLinks"},"createdAt":{"type":["string","null"]},"updatedAt":{"type":["string","null"]}},"required":["id","name","language","currency","businessType","branding","schedule","delivery","pickup","dineIn","whatsapp","biography","categories","slug","hidden","published","_links","createdAt","updatedAt"]},"PartialProductError":{"type":"object","properties":{"type":{"type":"string","enum":["plan_limit"]},"code":{"type":"string","enum":["products_over_limit"]},"message":{"type":"string"},"param":{"type":"string","enum":["products"]},"doc":{"type":"string"},"recoverable":{"type":"boolean","enum":[true]},"recovery":{"type":"object","properties":{"skippedCount":{"type":"integer","minimum":0},"skippedProducts":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0},"title":{"type":["string","null"]}},"required":["index","title"]}},"upgrade":{"type":"object","properties":{"currentPlan":{"type":"string"},"requiredPlan":{"type":"string"},"upgradeUrl":{"type":"string"}},"required":["currentPlan","requiredPlan","upgradeUrl"]}},"required":["skippedCount","skippedProducts","upgrade"]}},"required":["type","code","message","param","doc","recoverable","recovery"]},"StorefrontCreateResponse":{"type":"object","properties":{"storefront":{"$ref":"#/components/schemas/StorefrontDto"},"errors":{"type":"array","items":{"$ref":"#/components/schemas/PartialProductError"}}},"required":["storefront"]},"StorefrontResponse":{"type":"object","properties":{"storefront":{"$ref":"#/components/schemas/StorefrontDto"}},"required":["storefront"]},"StorefrontListItem":{"type":"object","properties":{"id":{"type":"string","pattern":"^stf_","example":"stf_abc123"},"name":{"type":"string"},"language":{"type":"string","enum":["es","en","pt"]},"currency":{"type":"string"},"businessType":{"type":["string","null"]},"branding":{"type":["object","null"],"properties":{"logoUrl":{"type":["string","null"]},"backgroundUrl":{"type":["string","null"]},"theme":{"type":["object","null"],"properties":{"primary":{"type":["string","null"]},"secondary":{"type":["string","null"]},"tertiary":{"type":["string","null"]}},"required":["primary","secondary","tertiary"]},"font":{"type":["string","null"]}},"required":["logoUrl","backgroundUrl","theme","font"]},"schedule":{"type":["object","null"],"properties":{"monday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"tuesday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"wednesday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"thursday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"friday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"saturday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]},"sunday":{"type":["object","null"],"properties":{"open":{"type":["string","null"]},"close":{"type":["string","null"]},"closed":{"type":["boolean","null"]}},"required":["open","close","closed"]}},"required":["monday","tuesday","wednesday","thursday","friday","saturday","sunday"]},"delivery":{"type":["object","null"],"properties":{"enabled":{"type":"boolean"},"type":{"type":["string","null"],"enum":["fixed","distance"]},"fixedPrice":{"type":["number","null"]},"ranges":{"type":["array","null"],"items":{"type":"object","properties":{"fromKm":{"type":"number"},"toKm":{"type":["number","null"]},"price":{"type":"number"}},"required":["fromKm","toKm","price"]}}},"required":["enabled","type","fixedPrice","ranges"]},"pickup":{"type":["boolean","null"]},"dineIn":{"type":["boolean","null"]},"whatsapp":{"type":["string","null"]},"biography":{"type":["object","null"],"properties":{"title":{"type":"string"},"description":{"type":"string"}},"required":["title","description"]},"categories":{"type":["array","null"],"items":{"type":"object","properties":{"name":{"type":"string"},"position":{"type":["integer","null"]}},"required":["name","position"]}},"slug":{"type":["string","null"]},"hidden":{"type":["boolean","null"]},"_links":{"$ref":"#/components/schemas/StorefrontLinks"},"createdAt":{"type":["string","null"]},"updatedAt":{"type":["string","null"]}},"required":["id","name","language","currency","businessType","branding","schedule","delivery","pickup","dineIn","whatsapp","biography","categories","slug","hidden","_links","createdAt","updatedAt"]},"StorefrontListResponse":{"type":"object","properties":{"storefronts":{"type":"array","items":{"$ref":"#/components/schemas/StorefrontListItem"}},"nextCursor":{"type":["string","null"]}},"required":["storefronts","nextCursor"]},"ExtraProductOption":{"type":"object","properties":{"title":{"type":"string"},"price":{"type":"number","minimum":0},"available":{"type":"boolean"},"stock":{"type":["integer","null"]}},"required":["title","price","available"]},"ExtraProductsCategory":{"type":"object","properties":{"title":{"type":"string"},"obligatory":{"type":"boolean"},"multipleOption":{"type":"boolean"},"maxOptions":{"type":"integer"},"minOptions":{"type":"integer"},"extraProducts":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ExtraProductOption"}}},"required":["title","obligatory","multipleOption","maxOptions","minOptions"]},"ProductDto":{"type":"object","properties":{"id":{"type":"string","pattern":"^prd_","example":"prd_abc123"},"title":{"type":"string"},"description":{"type":["string","null"]},"price":{"type":"number"},"salePrice":{"type":["number","null"]},"category":{"type":["string","null"]},"subcategory":{"type":["string","null"]},"imageUrl":{"type":["string","null"]},"thumbnailUrl":{"type":["string","null"]},"sku":{"type":["string","null"]},"slug":{"type":["string","null"]},"position":{"type":["integer","null"]},"cartProduct":{"type":["boolean","null"]},"hide":{"type":["boolean","null"]},"stock":{"type":["integer","null"]},"tags":{"type":["array","null"],"items":{"type":"string"}},"extraProductsCategory":{"type":["array","null"],"items":{"$ref":"#/components/schemas/ExtraProductsCategory"}},"imageProcessingPending":{"type":["boolean","null"]},"createdAt":{"type":["string","null"]},"updatedAt":{"type":["string","null"]}},"required":["id","title","description","price","salePrice","category","subcategory","imageUrl","thumbnailUrl","sku","slug","position","cartProduct","hide","stock","tags","extraProductsCategory","imageProcessingPending","createdAt","updatedAt"]},"ProductsCreateResponse":{"type":"object","properties":{"product":{"$ref":"#/components/schemas/ProductDto"}},"required":["product"]},"ProductsUpdateResponse":{"type":"object","properties":{"product":{"$ref":"#/components/schemas/ProductDto"}},"required":["product"]},"ProductListResponse":{"type":"object","properties":{"products":{"type":"array","items":{"$ref":"#/components/schemas/ProductDto"}},"nextCursor":{"type":["string","null"]}},"required":["products","nextCursor"]},"AppliedDefaults":{"type":"object","properties":{"language":{"type":"string","enum":["es","en","pt"]},"currency":{"type":"string"},"country":{"type":"string"},"businessType":{"type":"string"}},"required":["language","currency","country","businessType"]},"BootstrapResponse":{"type":"object","properties":{"userId":{"type":"string"},"storefrontId":{"type":["string","null"]},"userKey":{"type":"string","pattern":"^mk_user_"},"verificationStatus":{"type":"string","enum":["pending"]},"verificationExpiresAt":{"type":"string","format":"date-time"},"verificationDeliveryHint":{"type":"string","enum":["email-only"]},"appliedDefaults":{"$ref":"#/components/schemas/AppliedDefaults"},"idempotent":{"type":"boolean"},"errors":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}},"required":["type","code","message"]}}},"required":["userId","userKey","verificationStatus","verificationExpiresAt","verificationDeliveryHint","appliedDefaults"]},"VerifyResponse":{"type":"object","properties":{"userId":{"type":"string"},"verificationStatus":{"type":"string","enum":["verified"]}},"required":["userId","verificationStatus"]},"ResendResponse":{"type":"object","properties":{"verificationStatus":{"type":"string","enum":["pending"]},"verificationExpiresAt":{"type":"string","format":"date-time"}},"required":["verificationStatus","verificationExpiresAt"]},"UserDto":{"type":"object","properties":{"userId":{"type":"string"},"email":{"type":"string","format":"email"},"displayName":{"type":["string","null"]},"verificationStatus":{"type":["string","null"],"enum":["pending","verified"]},"plan":{"type":["number","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"verifiedAt":{"type":["string","null"],"format":"date-time"},"lastUserEvents":{"type":["array","null"],"items":{"type":"object","properties":{"type":{"type":"string"},"at":{"type":"string"},"reason":{"type":["string","null"]}},"required":["type","at"]}}},"required":["userId","email"]},"UserListResponse":{"type":"object","properties":{"users":{"type":"array","items":{"$ref":"#/components/schemas/UserDto"}},"nextCursor":{"type":["string","null"]}},"required":["users"]},"IssueUserKeyResponse":{"type":"object","properties":{"keyId":{"type":"string"},"rawKey":{"type":"string","pattern":"^mk_user_"},"prefix":{"type":"string"}},"required":["keyId","rawKey","prefix"]}},"parameters":{},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"mk_dev_* | mk_user_*"},"ApiKeyHeader":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Alternative to `Authorization: Bearer`. Same `mk_*` value. Use only when your environment cannot send the `Authorization` header."}}},"paths":{"/v1/me":{"get":{"summary":"Use this to confirm which user (or developer) the calling key acts as.","description":"Returns identity, plan info, and rate-limit window for the calling key. Branches on key type.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/storefronts":{"post":{"summary":"Use this when the user wants to create a new online storefront from scratch.","description":"Creates a storefront from a `StorefrontManifest`. Returns 201 with the full storefront. If the manifest contains more products than the plan allows, returns **207 Multi-Status** with the storefront created (up to plan cap) plus an `errors` array describing the over-cap items.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorefrontCreateResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"get":{"summary":"Use this when the user wants to discover storefronts on their Marea account.","description":"Returns the bearer user's storefronts ordered by createdAt DESC, paginated. `published` is omitted from list items — call GET /v1/storefronts/:id for the live publish status. Use the returned `nextCursor` (ISO createdAt) for the next page.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorefrontListResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/storefronts/:storefrontId":{"patch":{"summary":"Use this when the user wants to change ANY field of an existing storefront.","description":"Partial PATCH (mutability rule §6.18.1.1). Deep-merge for nested objects, full-replace for arrays.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorefrontResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"get":{"summary":"Use this when the user wants the full configuration of a single storefront.","description":"Returns the storefront DTO including the live `published` flag and `_links`. 404 on unknown id or cross-tenant.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorefrontResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/storefronts/:storefrontId/publish":{"post":{"summary":"Use this when the user is ready to take their storefront live.","description":"Publishes the current state of the storefront. Returns 402 if the plan does not permit publishing, 422 if the storefront has 0 products, 451 if ToS not accepted (PRD-7 hook). Idempotent on republish.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StorefrontResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/storefronts/:storefrontId/products":{"post":{"summary":"Use this when the user wants to add a product to an existing storefront.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductsCreateResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"get":{"summary":"Use this when the user wants to list products in a storefront's catalog.","description":"Returns products under the storefront ordered by createdAt DESC, paginated. Hidden products (`hide:true`) are excluded by default — pass `includeHidden=true` to see them. Use the returned `nextCursor` (ISO createdAt) for the next page.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductListResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/storefronts/:storefrontId/products/:productId":{"patch":{"summary":"Use this when the user wants to change ANY field of an existing product.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductsUpdateResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/users":{"post":{"summary":"Use this when an agent wants to create a Marea account on behalf of a user with one round-trip (account + storefront + verification email).","description":"Creates a Firebase Auth user + Firestore user doc + restricted user key + (optionally) a starter storefront via createMenuCore + sends a 6-digit verification email. Returns 201 (or 207 if the storefront manifest exceeded plan limits). The userKey is returned ONCE — store it.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BootstrapResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"get":{"summary":"Use this to list every user this developer key has bootstrapped (paginated 50/page).","description":"Returns users where createdByDeveloper.keyId === ctx.keyId, ordered by createdAt DESC. Use the returned `nextCursor` (createdAt ISO string) for the next page.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserListResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/users/:userId/verify":{"post":{"summary":"Use this when the user has read back the 6-digit code from their email and you want to upgrade the user-key to full scope.","description":"Validates the 6-digit code (3 attempts max), upgrades the bootstrap user-key from restricted to full scope (same key — no rotation), flips agentBootstrapped→false + verificationStatus→verified, fires the user.verified webhook stub. Cross-tenant/wrong-id → 404 leak-less.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/users/:userId/resendVerification":{"post":{"summary":"Use this when the verification email may have been lost or the code expired and you want to issue a fresh code without re-bootstrapping.","description":"Per-user rate-limited (3/hour, 5/day). Overwrites the existing apiVerificationCodes/{email} doc — old code is voided automatically. Returns the new expiry timestamp.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResendResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/users/:userId":{"get":{"summary":"Use this to poll the status of a user you previously bootstrapped (verificationStatus, plan, recent events).","description":"Returns the user DTO. Cross-developer isolation: only users that THIS developer key bootstrapped are visible — wrong-id or other-developer's-user → 404 leak-less per RFC §10.4.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDto"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/users/:userId/keys":{"post":{"summary":"Use this to issue an additional restricted user key for a verified user you previously bootstrapped (e.g. a second integration).","description":"Validates that the user was bootstrapped by THIS developer and is verified (verificationStatus===\"verified\"). Returns the raw user key once. Cross-developer attempt → 404 leak-less; pre-verify call → 422.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueUserKeyResponse"}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/webhook_endpoints":{"post":{"summary":"Use this when you want to register a webhook endpoint that receives one or more event types (`user.verified`, `user.cancelled`, `order.*`).","description":"Creates a webhook endpoint as a first-class object. The returned `signingSecret` is the only time the secret is visible — store it now; rotate via `POST /v1/webhook_endpoints/{id}/rotate-secret` if lost. Per-event subscription is controlled by `subscribedEvents`. A developer endpoint can subscribe to `order.*` events from any storefront the caller bootstrapped — Marea resolves the merchant → developer chain at dispatch time, so one endpoint covers every storefront. Hard caps: 16 endpoints per account; URL ≤2048 chars; HTTPS only; rejects loopback / private / metadata hostnames.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"endpointId":{"type":"string"},"scope":{"type":"string","enum":["developer","merchant"]},"url":{"type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"subscribedEvents":{"type":"array","items":{"type":"string","enum":["user.verified","user.cancelled","order.created","order.status_updated","order.paid"]}},"signingSecretVersion":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"lastDeliveryAt":{"type":["string","null"]},"lastDeliveryStatus":{"type":["string","null"],"enum":["success","failure"]},"consecutiveFailures":{"type":"integer","minimum":0},"signingSecret":{"type":"string","pattern":"^[0-9a-f]{64}$"}},"required":["endpointId","scope","url","description","enabled","subscribedEvents","signingSecretVersion","createdAt","updatedAt","lastDeliveryAt","lastDeliveryStatus","consecutiveFailures","signingSecret"]}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"get":{"summary":"Use this when you want to list every webhook endpoint owned by the caller (developer scope).","description":"Returns up to 16 endpoints (cap per account). Never returns the signing secret — use `POST /v1/webhook_endpoints/{id}/rotate-secret` if you need a new one.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"endpoints":{"type":"array","items":{"type":"object","properties":{"endpointId":{"type":"string"},"scope":{"type":"string","enum":["developer","merchant"]},"url":{"type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"subscribedEvents":{"type":"array","items":{"type":"string","enum":["user.verified","user.cancelled","order.created","order.status_updated","order.paid"]}},"signingSecretVersion":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"lastDeliveryAt":{"type":["string","null"]},"lastDeliveryStatus":{"type":["string","null"],"enum":["success","failure"]},"consecutiveFailures":{"type":"integer","minimum":0}},"required":["endpointId","scope","url","description","enabled","subscribedEvents","signingSecretVersion","createdAt","updatedAt","lastDeliveryAt","lastDeliveryStatus","consecutiveFailures"]}}},"required":["endpoints"]}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/webhook_endpoints/:id":{"get":{"summary":"Use this when you want to fetch a single webhook endpoint by its id.","description":"Returns the endpoint excluding the signing secret. Useful for verifying current event subscriptions, enablement status, and recent-delivery summary.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"endpointId":{"type":"string"},"scope":{"type":"string","enum":["developer","merchant"]},"url":{"type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"subscribedEvents":{"type":"array","items":{"type":"string","enum":["user.verified","user.cancelled","order.created","order.status_updated","order.paid"]}},"signingSecretVersion":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"lastDeliveryAt":{"type":["string","null"]},"lastDeliveryStatus":{"type":["string","null"],"enum":["success","failure"]},"consecutiveFailures":{"type":"integer","minimum":0}},"required":["endpointId","scope","url","description","enabled","subscribedEvents","signingSecretVersion","createdAt","updatedAt","lastDeliveryAt","lastDeliveryStatus","consecutiveFailures"]}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"post":{"summary":"Use this when you want to patch one or more fields of an existing webhook endpoint (url, description, enabled, subscribedEvents).","description":"Accepts a partial update; only the fields present in the body are modified. Cannot rotate the signing secret here — use the dedicated rotate-secret callable / endpoint. Does NOT return the signing secret.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"endpointId":{"type":"string"},"scope":{"type":"string","enum":["developer","merchant"]},"url":{"type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"subscribedEvents":{"type":"array","items":{"type":"string","enum":["user.verified","user.cancelled","order.created","order.status_updated","order.paid"]}},"signingSecretVersion":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"lastDeliveryAt":{"type":["string","null"]},"lastDeliveryStatus":{"type":["string","null"],"enum":["success","failure"]},"consecutiveFailures":{"type":"integer","minimum":0}},"required":["endpointId","scope","url","description","enabled","subscribedEvents","signingSecretVersion","createdAt","updatedAt","lastDeliveryAt","lastDeliveryStatus","consecutiveFailures"]}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}},"delete":{"summary":"Use this when you want to permanently delete a webhook endpoint. To stop dispatch without losing the URL, use `enabled: false` via the update endpoint instead.","description":"Hard delete — there is no soft-delete state for endpoints. Idempotent for 404 callers (returns 404 if already absent).","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"endpointId":{"type":"string"}},"required":["ok","endpointId"]}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}},"/v1/webhook_endpoints/:id/rotate-secret":{"post":{"summary":"Use this when you want to rotate the signing secret of a webhook endpoint. Returns the new secret ONCE; the old secret stops working immediately.","description":"No overlap window in v1 — coordinate the rotation with your receiver. The returned `signingSecret` is the only time the new secret is visible; store it before responding to the next webhook. Bumps `signingSecretVersion` by one.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"endpointId":{"type":"string"},"scope":{"type":"string","enum":["developer","merchant"]},"url":{"type":"string"},"description":{"type":["string","null"]},"enabled":{"type":"boolean"},"subscribedEvents":{"type":"array","items":{"type":"string","enum":["user.verified","user.cancelled","order.created","order.status_updated","order.paid"]}},"signingSecretVersion":{"type":"integer"},"createdAt":{"type":"string"},"updatedAt":{"type":"string"},"lastDeliveryAt":{"type":["string","null"]},"lastDeliveryStatus":{"type":["string","null"],"enum":["success","failure"]},"consecutiveFailures":{"type":"integer","minimum":0},"signingSecret":{"type":"string","pattern":"^[0-9a-f]{64}$"}},"required":["endpointId","scope","url","description","enabled","subscribedEvents","signingSecretVersion","createdAt","updatedAt","lastDeliveryAt","lastDeliveryStatus","consecutiveFailures","signingSecret"]}}}},"400":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"401":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"403":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"404":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"409":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"410":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"413":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"429":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"500":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}},"503":{"description":"§9.6 error envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorResponse"}}}}}}}},"webhooks":{}}