{"openapi":"3.1.0","info":{"title":"Peak Commerce Agent API v1","description":"Action-oriented API for AI agents to manage accounts, subscriptions, orders, payments, invoices, and webhooks. Every response includes a `nextActions` array for HATEOAS-style navigation and a `requestId` for correlation.\n\n## Conventions\n\n### Request IDs\nEvery request is assigned a unique `X-Request-ID`. Supply your own (≤64 alphanumeric/dash/underscore chars) or the server will generate one. The same ID is returned in the response header and in every JSON body as `requestId`.\n\n### Pagination\nList endpoints accept `limit` (1–100, default 20), `offset` (default 0), `sort` (field name), and `sortDir` (`asc`|`desc`). Responses include a `pagination` envelope: `{ total, limit, offset, hasMore }`.\n\n### Idempotency\nAll `POST` and `PATCH` endpoints accept an `Idempotency-Key` header (≤255 chars). Replays with the same key+route within 24 hours return the original response without executing the operation again. The replayed response includes `X-Idempotency-Replayed: true`.\n\n### Errors\nAll errors use a stable envelope: `{ error: { code, message, details? }, requestId }`. `code` is a stable machine-readable string. `details` is present on validation errors and contains per-field information.\n\n### Versioning\nThe API version is embedded in the path (`/api/v1`). Deprecated endpoints will carry `Deprecation` and `Sunset` response headers before removal.\n\n## Webhook Signature Scheme\n\nEvery webhook POST request is signed using HMAC-SHA256. The signing secret is returned once when the subscription is created (`POST /webhooks`) — store it securely; it is never returned again.\n\n### Headers sent with each delivery\n\n| Header | Value |\n|---|---|\n| `X-Webhook-Signature` | `sha256=<hex-digest>` |\n| `X-Webhook-Event` | event type name (e.g. `subscription.created`) |\n| `X-Webhook-Timestamp` | ISO 8601 timestamp of the event |\n\n### Verifying the signature\n\n1. Read the raw request body as a UTF-8 string — do **not** parse it first.\n2. Compute `HMAC-SHA256(secret, rawBody)` and hex-encode the digest.\n3. Compare the result to the value of `X-Webhook-Signature` after stripping the `sha256=` prefix. Use a constant-time comparison to prevent timing attacks.\n\nExample (Node.js):\n```js\nconst crypto = require('crypto');\nfunction verifyWebhook(secret, rawBody, signatureHeader) {\n  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');\n  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));\n}\n```\n\n### Retry policy and dead-lettering\n\nFailed deliveries are retried with exponential backoff (2^attempt seconds) up to 5 attempts. After the 5th failure the delivery enters `dead_letter` status. Dead-lettered deliveries are queryable via `GET /webhooks/{id}/deliveries?status=dead_letter` and can be re-enqueued at any time via `POST /webhooks/{id}/deliveries/{deliveryId}/replay`.","version":"1.0.0"},"servers":[{"url":"https://peakcommerce.app/api/v1","description":"Production"},{"url":"https://sandbox.peakcommerce.app/api/v1","description":"Sandbox"}],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Scoped API key. Scopes: read, commerce, admin."},"BearerAuth":{"type":"http","scheme":"bearer"}},"parameters":{"Limit":{"name":"limit","in":"query","description":"Max items to return (1–100, default 20)","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},"Offset":{"name":"offset","in":"query","description":"Number of items to skip (default 0)","schema":{"type":"integer","minimum":0,"default":0}},"Sort":{"name":"sort","in":"query","description":"Field to sort by","schema":{"type":"string"}},"SortDir":{"name":"sortDir","in":"query","description":"Sort direction","schema":{"type":"string","enum":["asc","desc"],"default":"asc"}},"StatusFilter":{"name":"status","in":"query","description":"Filter by status","schema":{"type":"string"}}},"headers":{"X-Request-ID":{"description":"Unique request identifier for correlation","schema":{"type":"string"}},"Idempotency-Key":{"description":"Client-supplied idempotency key (≤255 chars). Replays within 24h return the original response.","schema":{"type":"string"}},"X-Idempotency-Replayed":{"description":"Present with value `true` when the response is a cached replay of a prior idempotent request","schema":{"type":"string","enum":["true"]}},"Sunset":{"description":"RFC 8594 date after which this endpoint will be removed","schema":{"type":"string"}},"Deprecation":{"description":"RFC 8594 deprecation date","schema":{"type":"string"}}},"schemas":{"ErrorDetail":{"type":"object","required":["field","message"],"properties":{"field":{"type":"string"},"message":{"type":"string"}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code (e.g. not_found, validation_failed, policy_violation, internal_error)"},"message":{"type":"string","description":"Human-readable error description"},"details":{"type":"array","items":{"$ref":"#/components/schemas/ErrorDetail"},"description":"Per-field validation details (present on validation_failed errors)"}}},"requestId":{"type":"string","description":"Unique request ID for correlation with server logs"}}},"Pagination":{"type":"object","required":["total","limit","offset","hasMore"],"properties":{"total":{"type":"integer","description":"Total number of items matching the query"},"limit":{"type":"integer"},"offset":{"type":"integer"},"hasMore":{"type":"boolean","description":"Whether more items exist beyond the current page"}}},"NextAction":{"type":"object","properties":{"rel":{"type":"string"},"method":{"type":"string"},"href":{"type":"string"}}},"Account":{"type":"object","properties":{"id":{"type":"string"},"accountNumber":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"},"balance":{"type":"number"},"currency":{"type":"string"},"billToContact":{"type":"object"},"soldToContact":{"type":"object"}}},"Subscription":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"priceCents":{"type":"integer"},"currency":{"type":"string"},"billingInterval":{"type":"string"}}},"Order":{"type":"object","properties":{"id":{"type":"string"},"orderNumber":{"type":"string"},"status":{"type":"string"},"totalCents":{"type":"integer"},"currency":{"type":"string"},"items":{"type":"array"}}},"Invoice":{"type":"object","properties":{"id":{"type":"string"},"invoiceNumber":{"type":"string"},"invoiceDate":{"type":"string"},"dueDate":{"type":"string"},"amount":{"type":"number"},"balance":{"type":"number"},"currency":{"type":"string"},"status":{"type":"string"}}},"PaymentSession":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"amountCents":{"type":"integer"},"currency":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"PaymentMethod":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"cardType":{"type":"string"},"lastFour":{"type":"string"},"expirationMonth":{"type":"integer"},"expirationYear":{"type":"integer"},"isDefault":{"type":"boolean"}}},"WebhookSubscription":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"WebhookDelivery":{"type":"object","description":"A single webhook delivery attempt record.","properties":{"id":{"type":"string","format":"uuid"},"webhookSubscriptionId":{"type":"string","format":"uuid"},"eventType":{"type":"string","description":"The event type that triggered this delivery."},"status":{"type":"string","enum":["pending","retrying","delivered","dead_letter"],"description":"Current delivery status. `dead_letter` means max retry attempts were exhausted."},"statusCode":{"type":"integer","nullable":true,"description":"HTTP status code returned by the consumer endpoint."},"responseBody":{"type":"string","nullable":true,"description":"First 1000 chars of the consumer response body."},"attempts":{"type":"integer","description":"Number of delivery attempts made so far."},"maxAttempts":{"type":"integer","description":"Maximum number of attempts before dead-lettering."},"lastAttemptAt":{"type":"string","format":"date-time","nullable":true},"nextRetryAt":{"type":"string","format":"date-time","nullable":true,"description":"When the next retry is scheduled (null if delivered or dead-lettered)."},"createdAt":{"type":"string","format":"date-time"}}},"WebhookEventType":{"type":"object","properties":{"name":{"type":"string","description":"Event type identifier to use in subscription `events` arrays."},"category":{"type":"string","description":"Logical grouping of the event."},"description":{"type":"string","description":"Human-readable description of when this event fires."}}},"Product":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"sku":{"type":"string"},"description":{"type":"string"},"category":{"type":"string"},"productType":{"type":"string"},"priceCents":{"type":"integer"},"currency":{"type":"string"},"billingInterval":{"type":"string"},"isActive":{"type":"boolean"},"lifecycleRules":{"type":"object","description":"Applicable business rules governing lifecycle operations","properties":{"upgrade":{"type":"object","nullable":true,"description":"Rule for plan upgrades (timing, proration)"},"downgrade":{"type":"object","nullable":true,"description":"Rule for plan downgrades"},"cancellation":{"type":"object","nullable":true,"description":"Rule for cancellations"},"addOn":{"type":"object","nullable":true,"description":"Rule for add-on operations"}}},"pricingRules":{"type":"object","properties":{"hasDynamicPricing":{"type":"boolean","description":"Whether multiple pricing tiers exist"},"pricingTierCount":{"type":"integer","description":"Number of pricing tiers"}}}}},"CatalogResponse":{"type":"object","properties":{"products":{"type":"array","items":{"$ref":"#/components/schemas/Product"},"description":"Enriched product list with lifecycle and pricing rules"},"paymentPages":{"type":"array","items":{"type":"object"},"description":"Payment page summaries"}}},"PreviewResponse":{"type":"object","description":"Preview of an operation showing effective date, financial impact, applicable business rule, and policy evaluation. Read-only — no state changes.","properties":{"subscriptionId":{"type":"string"},"currentProduct":{"type":"object","nullable":true},"targetProduct":{"type":"object","nullable":true},"direction":{"type":"string","enum":["upgrade","downgrade"]},"effectiveDate":{"type":"string","format":"date-time"},"financialImpact":{"type":"object","properties":{"currentPriceCents":{"type":"integer"},"newPriceCents":{"type":"integer"},"creditCents":{"type":"integer"},"chargeCents":{"type":"integer"},"netCents":{"type":"integer"},"currency":{"type":"string"}}},"businessRule":{"type":"object","nullable":true,"description":"The business rule governing this operation, or null if no rule applies"},"policyEvaluation":{"type":"object","properties":{"allowed":{"type":"boolean"},"evaluations":{"type":"array","items":{"type":"object"}}}},"resolvedPrice":{"type":"object","description":"Resolved pricing including tier information"}}},"PricingResolution":{"type":"object","description":"Resolved effective price after applying pricing tiers, quantity, and offer discounts","properties":{"productId":{"type":"string"},"productName":{"type":"string"},"basePriceCents":{"type":"integer","description":"Price before offer discounts"},"resolvedPriceCents":{"type":"integer","description":"Final price after all rules and discounts"},"currency":{"type":"string"},"quantity":{"type":"integer"},"context":{"type":"object","description":"Customer context used for resolution"},"rulesApplied":{"type":"array","items":{"type":"object","properties":{"rule":{"type":"string"},"type":{"type":"string"},"adjustment":{"type":"string"},"detail":{"type":"string"}}}},"availableOffers":{"type":"array","items":{"type":"object"}}}},"Manifest":{"type":"object","properties":{"operations":{"type":"array","items":{"type":"object"}},"paymentPages":{"type":"array","items":{"type":"object"}},"capabilities":{"type":"object"}}},"Address":{"type":"object","description":"Geographic address used for tax and shipping calculation.","properties":{"country":{"type":"string","description":"ISO 3166-1 alpha-2 or alpha-3 country code"},"state":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"line1":{"type":"string"}}},"TaxBreakdownLine":{"type":"object","properties":{"description":{"type":"string"},"amountCents":{"type":"integer"},"rate":{"type":"number"}}},"TaxResult":{"type":"object","properties":{"amountCents":{"type":"integer","description":"Total tax in cents"},"rate":{"type":"number","description":"Effective tax rate (0.0–1.0)"},"provider":{"type":"string","description":"Tax provider identifier (e.g. 'none', 'avalara')"},"breakdown":{"type":"array","items":{"$ref":"#/components/schemas/TaxBreakdownLine"}}}},"ShippingOption":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"carrier":{"type":"string"},"estimatedDays":{"type":"integer","nullable":true},"priceCents":{"type":"integer"},"currency":{"type":"string"},"description":{"type":"string"}}},"OrderTotalPreview":{"type":"object","description":"Breakdown of an order total including line items, tax, and shipping. Read-only — does not create an order.","properties":{"subtotalCents":{"type":"integer"},"taxAmountCents":{"type":"integer"},"shippingAmountCents":{"type":"integer"},"grandTotalCents":{"type":"integer"},"currency":{"type":"string"},"tax":{"$ref":"#/components/schemas/TaxResult"},"shipping":{"type":"object","properties":{"selectedOption":{"$ref":"#/components/schemas/ShippingOption","nullable":true},"availableOptions":{"type":"array","items":{"$ref":"#/components/schemas/ShippingOption"}}}},"pricingBreakdown":{"type":"array","items":{"type":"object","properties":{"productId":{"type":"string"},"name":{"type":"string"},"quantity":{"type":"integer"},"unitPriceCents":{"type":"integer"},"lineTotalCents":{"type":"integer"},"priceSource":{"type":"string","enum":["pricing_engine","caller_supplied"]}}}}}},"UsageSummary":{"type":"object","description":"Per-key API usage metrics aggregated by route and time bucket","properties":{"summary":{"type":"object","properties":{"totalRequests":{"type":"integer","description":"Total API requests in the window"},"totalErrors":{"type":"integer","description":"Requests that returned HTTP 4xx or 5xx"},"totalRateLimited":{"type":"integer","description":"Requests that were rate-limited (HTTP 429)"},"avgLatencyMs":{"type":"integer","description":"Average server latency in milliseconds"},"errorRate":{"type":"number","description":"Fraction of requests that were errors (0.0–1.0)"}}},"byRoute":{"type":"array","description":"Breakdown per route+method, sorted by request volume descending","items":{"type":"object","properties":{"route":{"type":"string","example":"/accounts/:id"},"method":{"type":"string","example":"GET"},"requests":{"type":"integer"},"errors":{"type":"integer"},"rateLimited":{"type":"integer"},"avgLatencyMs":{"type":"integer"}}}},"byBucket":{"type":"array","description":"Time series at 1-minute granularity, ordered chronologically","items":{"type":"object","properties":{"timeBucket":{"type":"string","format":"date-time"},"requests":{"type":"integer"},"errors":{"type":"integer"},"rateLimited":{"type":"integer"},"avgLatencyMs":{"type":"integer"}}}},"window":{"type":"object","properties":{"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"},"granularity":{"type":"string","example":"minute"}}},"apiKey":{"type":"object","nullable":true,"description":"Details of the API key the usage is scoped to (absent when viewing all keys)","properties":{"id":{"type":"string"},"prefix":{"type":"string"},"name":{"type":"string","nullable":true}}}}},"ComponentStatus":{"type":"object","required":["name","status"],"properties":{"name":{"type":"string","description":"Component identifier","example":"database"},"status":{"type":"string","enum":["operational","degraded","incident"],"description":"Current health of the component"},"latencyMs":{"type":"integer","nullable":true,"description":"Round-trip latency in ms (where applicable)"},"detail":{"type":"string","nullable":true,"description":"Human-readable detail about the component state"}}},"StatusResponse":{"type":"object","required":["status","components","cachedAt"],"properties":{"status":{"type":"string","enum":["operational","degraded","incident"],"description":"Worst-case status across all components"},"components":{"type":"array","items":{"$ref":"#/components/schemas/ComponentStatus"},"description":"Individual component health: database, billing_adapter, webhooks, cache"},"cachedAt":{"type":"string","format":"date-time","description":"When this status snapshot was computed (TTL: 30 s)"}}},"ErrorCodes":{"type":"object","description":"Catalog of all stable v1 API error codes. Every error response from /api/v1 includes a `code` field that matches one of these entries. Use `retryable` to decide whether to back off and retry.","properties":{"codes":{"type":"array","items":{"type":"object","required":["code","httpStatus","description","retryable"],"properties":{"code":{"type":"string","description":"Stable machine-readable error code","example":"rate_limit_exceeded"},"description":{"type":"string","description":"What the error means and how to resolve it"},"retryable":{"type":"boolean","description":"Whether the caller should retry (with back-off) after this error"}}}}}},"Refund":{"type":"object","description":"A refund issued against a successful payment session","properties":{"id":{"type":"string"},"paymentId":{"type":"string"},"invoiceId":{"type":"string","nullable":true},"amountCents":{"type":"integer"},"currency":{"type":"string"},"status":{"type":"string","enum":["pending","succeeded","failed"]},"isFullRefund":{"type":"boolean"},"reason":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CreditApplication":{"type":"object","properties":{"paymentId":{"type":"string","nullable":true},"amountCents":{"type":"integer"},"appliedAt":{"type":"string","format":"date-time"}}},"Credit":{"type":"object","description":"A credit issued to an account that can be applied to reduce future payment amounts","properties":{"id":{"type":"string"},"accountId":{"type":"string"},"amountCents":{"type":"integer","description":"Original credit amount"},"remainingCents":{"type":"integer","description":"Remaining unapplied balance"},"currency":{"type":"string"},"status":{"type":"string","enum":["active","applied","expired","cancelled"]},"reason":{"type":"string","nullable":true},"expiresAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"applications":{"type":"array","items":{"$ref":"#/components/schemas/CreditApplication"}}}},"CreditBalance":{"type":"object","description":"Aggregate credit balance for an account","properties":{"accountId":{"type":"string"},"balanceCents":{"type":"integer","description":"Total active, non-expired credit balance in cents"},"currency":{"type":"string"},"activeCredits":{"type":"integer","description":"Number of active non-expired credits"},"expiredCredits":{"type":"integer","description":"Number of credits that have expired"},"totalCredits":{"type":"integer","description":"Total credit records (all statuses)"}}},"AdminUser":{"type":"object","description":"A platform user (admin, customer, CSR, or partner)","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"portalType":{"type":"string","enum":["admin","customer","csr","partner"]},"profileId":{"type":"string","format":"uuid"},"isActive":{"type":"boolean"},"externalAccountId":{"type":"string","nullable":true},"externalContactId":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"Role":{"type":"object","description":"A user profile/role defining a named set of permissions","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"role":{"type":"string","enum":["admin","customer","csr","partner"]},"isActive":{"type":"boolean"},"isSystem":{"type":"boolean"},"permissions":{"type":"object","description":"Structured permission set for this role"},"createdAt":{"type":"string","format":"date-time"}}},"AdminPage":{"type":"object","description":"A portal page, payment page, storefront page, or checkout page","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"type":{"type":"string"},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"CustomComponent":{"type":"object","description":"A custom UI component (code or template type) for the Puck editor","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"displayName":{"type":"string","nullable":true},"description":{"type":"string","nullable":true},"componentType":{"type":"string","enum":["code","template"]},"category":{"type":"string","nullable":true},"editorContexts":{"type":"array","items":{"type":"string"}},"audienceRoles":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"PageTemplate":{"type":"object","description":"A reusable page template for the editor","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"pageType":{"type":"string"},"thumbnail":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"Partner":{"type":"object","description":"A partner user enriched with their partner profile","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"isActive":{"type":"boolean"},"partnerProfile":{"type":"object","nullable":true,"properties":{"companyName":{"type":"string","nullable":true},"contactName":{"type":"string","nullable":true},"contactEmail":{"type":"string","nullable":true},"tier":{"type":"string","nullable":true},"commissionStructureId":{"type":"string","nullable":true}}}}},"CommissionStructure":{"type":"object","description":"A commission calculation structure for partner earnings","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"commissionType":{"type":"string"},"rate":{"type":"number","nullable":true},"flatAmount":{"type":"number","nullable":true},"currency":{"type":"string","nullable":true},"isActive":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"}}},"AuditLog":{"type":"object","description":"An immutable record of a platform action","properties":{"id":{"type":"string","format":"uuid"},"userId":{"type":"string","format":"uuid","nullable":true,"description":"The user who performed the action (null for API key actions)"},"action":{"type":"string","description":"Namespaced action identifier (e.g. api.user.create)"},"resourceType":{"type":"string","nullable":true},"resourceId":{"type":"string","nullable":true},"details":{"type":"object","description":"Action-specific metadata"},"ipAddress":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"ApiKeyRecord":{"type":"object","description":"An API key record (secret is never returned except at create/rotate time)","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"keyPrefix":{"type":"string","description":"First 10 characters of the key for identification"},"scopes":{"type":"array","items":{"type":"string","enum":["read","commerce","admin"]}},"rateLimitTier":{"type":"string","enum":["standard","premium","unlimited"]},"isActive":{"type":"boolean"},"revokedAt":{"type":"string","format":"date-time","nullable":true},"lastUsedAt":{"type":"string","format":"date-time","nullable":true},"expiresAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"ApiKeyCreateResponse":{"type":"object","description":"Response from creating or rotating an API key — includes the one-time plaintext secret","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/ApiKeyRecord"},{"type":"object","properties":{"secret":{"type":"string","description":"Plaintext API key — shown only once, store securely"}},"required":["secret"]}]},"meta":{"type":"object","properties":{"secretNote":{"type":"string"},"replacedKeyId":{"type":"string","description":"ID of the key that was revoked (rotate only)"}}},"requestId":{"type":"string"}}},"ErrorCodesExample":{"type":"object","example":{"codes":[{"code":"api_key_required","httpStatus":401,"description":"No API key was supplied.","retryable":false},{"code":"rate_limit_exceeded","httpStatus":429,"description":"Rate limit exceeded. Check X-RateLimit-Reset.","retryable":true},{"code":"validation_failed","httpStatus":400,"description":"Request body failed schema validation. See details.","retryable":false},{"code":"not_found","httpStatus":404,"description":"The resource does not exist.","retryable":false},{"code":"internal_error","httpStatus":500,"description":"Unexpected server error. Include requestId in support tickets.","retryable":true}]}}}},"paths":{"/manifest":{"get":{"summary":"Get tenant-level capability manifest describing all available operations","operationId":"getManifest","tags":["Discovery"],"responses":{"200":{"description":"Tenant capability manifest","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Manifest"}}}}}}},"/catalog":{"get":{"summary":"List catalog products enriched with lifecycle rules and pricing indicators, plus payment pages","operationId":"getCatalog","tags":["Discovery"],"responses":{"200":{"description":"Enriched catalog with products and payment pages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogResponse"}}}}}}},"/capabilities":{"get":{"summary":"Discover merchant capabilities including payment methods and supported currencies","operationId":"getCapabilities","tags":["Discovery"],"responses":{"200":{"description":"Merchant capabilities"}}}},"/accounts":{"post":{"summary":"Create a new account (organization)","operationId":"createAccount","tags":["Accounts"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"externalId":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"website":{"type":"string"},"industry":{"type":"string"}}}}}},"responses":{"201":{"description":"Account created"},"400":{"description":"Validation error"}}}},"/accounts/{id}":{"get":{"summary":"Get account details by ID. For external billing accounts, fetches from the billing adapter.","operationId":"getAccount","tags":["Accounts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Account details"},"404":{"description":"Account not found"}}},"patch":{"summary":"Update account details","operationId":"updateAccount","tags":["Accounts"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"}}}}}},"responses":{"200":{"description":"Account updated"},"404":{"description":"Not found"}}}},"/accounts/{id}/invoices":{"get":{"summary":"List all invoices for an account via the billing adapter","operationId":"getAccountInvoices","tags":["Invoices"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"$ref":"#/components/parameters/Sort"},{"$ref":"#/components/parameters/SortDir"}],"responses":{"200":{"description":"Paginated list of invoices","headers":{"X-Request-ID":{"$ref":"#/components/headers/X-Request-ID"}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No billing integration configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/accounts/{id}/subscriptions":{"get":{"summary":"List subscriptions for an account via the billing adapter","operationId":"getAccountSubscriptions","tags":["Subscriptions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"$ref":"#/components/parameters/Sort"},{"$ref":"#/components/parameters/SortDir"}],"responses":{"200":{"description":"Paginated list of subscriptions","headers":{"X-Request-ID":{"$ref":"#/components/headers/X-Request-ID"}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No billing integration configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/accounts/{id}/payment-methods":{"get":{"summary":"List payment methods for an account via the billing adapter","operationId":"getAccountPaymentMethods","tags":["PaymentMethods"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"}],"responses":{"200":{"description":"Paginated list of payment methods","headers":{"X-Request-ID":{"$ref":"#/components/headers/X-Request-ID"}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No billing integration configured","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/subscriptions":{"get":{"summary":"List all subscriptions for the tenant","operationId":"listSubscriptions","tags":["Subscriptions"],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"$ref":"#/components/parameters/Sort"},{"$ref":"#/components/parameters/SortDir"},{"$ref":"#/components/parameters/StatusFilter"}],"responses":{"200":{"description":"Paginated list of subscriptions","headers":{"X-Request-ID":{"$ref":"#/components/headers/X-Request-ID"}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a new subscription","operationId":"createSubscription","tags":["Subscriptions"],"parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key to safely retry without creating duplicates","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["productId"],"properties":{"productId":{"type":"string"},"contactId":{"type":"string"},"organizationId":{"type":"string"},"priceCents":{"type":"integer"},"currency":{"type":"string"},"billingInterval":{"type":"string"},"externalId":{"type":"string"}}}}}},"responses":{"201":{"description":"Subscription created"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/subscriptions/{id}":{"get":{"summary":"Get subscription details","operationId":"getSubscription","tags":["Subscriptions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Subscription details"}}}},"/subscriptions/{id}/change-plan":{"post":{"summary":"Change the plan for a subscription (update product, price, interval)","operationId":"changeSubscriptionPlan","tags":["Subscriptions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"productId":{"type":"string"},"priceCents":{"type":"integer"},"billingInterval":{"type":"string"}}}}}},"responses":{"200":{"description":"Plan changed"}}}},"/subscriptions/{id}/cancel":{"post":{"summary":"Cancel a subscription","operationId":"cancelSubscription","tags":["Subscriptions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Subscription cancelled"}}}},"/subscriptions/{id}/renew":{"post":{"summary":"Renew a subscription","operationId":"renewSubscription","tags":["Subscriptions"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Subscription renewed"}}}},"/orders":{"get":{"summary":"List all orders for the tenant","operationId":"listOrders","tags":["Orders"],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"$ref":"#/components/parameters/Sort"},{"$ref":"#/components/parameters/SortDir"},{"$ref":"#/components/parameters/StatusFilter"}],"responses":{"200":{"description":"Paginated list of orders","headers":{"X-Request-ID":{"$ref":"#/components/headers/X-Request-ID"}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a new order","operationId":"createOrder","tags":["Orders"],"parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key to safely retry without creating duplicates","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cartId":{"type":"string","description":"When set, the order is built from this cart and its offer discount is enforced against the tenant's discount_cap policy"},"contactId":{"type":"string"},"organizationId":{"type":"string"},"items":{"type":"array"},"totalCents":{"type":"integer"},"currency":{"type":"string"}}}}}},"responses":{"201":{"description":"Order created"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Policy violation (e.g. discount exceeds the tenant cap)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Cart not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders/{id}":{"get":{"summary":"Get order details","operationId":"getOrder","tags":["Orders"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Order details"}}},"patch":{"summary":"Update order status or details","operationId":"updateOrder","tags":["Orders"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string"},"items":{"type":"array"},"totalCents":{"type":"integer"}}}}}},"responses":{"200":{"description":"Order updated"}}}},"/invoices/{id}/pay":{"post":{"summary":"Initiate payment for a specific invoice","operationId":"payInvoice","tags":["Invoices"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId","amountCents","currency"],"properties":{"accountId":{"type":"string"},"amountCents":{"type":"integer"},"currency":{"type":"string"}}}}}},"responses":{"201":{"description":"Payment session created for invoice"}}}},"/payments":{"get":{"summary":"List all payment sessions for the tenant","operationId":"listPaymentSessions","tags":["Payments"],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"$ref":"#/components/parameters/Sort"},{"$ref":"#/components/parameters/SortDir"},{"$ref":"#/components/parameters/StatusFilter"}],"responses":{"200":{"description":"Paginated list of payment sessions","headers":{"X-Request-ID":{"$ref":"#/components/headers/X-Request-ID"}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create a payment session","operationId":"createPayment","tags":["Payments"],"parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key to safely retry without creating duplicates","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId","amountCents","currency"],"properties":{"accountId":{"type":"string"},"amountCents":{"type":"integer"},"currency":{"type":"string"},"invoiceId":{"type":"string"},"paymentPageSlug":{"type":"string"}}}}}},"responses":{"201":{"description":"Payment session created"},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/payments/{id}":{"get":{"summary":"Get payment session details","operationId":"getPaymentSession","tags":["Payments"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Payment session details"}}}},"/payments/{id}/complete":{"post":{"summary":"Mark a payment session as completed","operationId":"completePaymentSession","tags":["Payments"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Payment session completed"}}}},"/sessions":{"get":{"summary":"List journey sessions for the tenant","operationId":"listJourneySessions","tags":["Sessions"],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"$ref":"#/components/parameters/Sort"},{"$ref":"#/components/parameters/SortDir"},{"$ref":"#/components/parameters/StatusFilter"},{"name":"journeyId","in":"query","description":"Filter to a specific journey","schema":{"type":"string"}},{"name":"outcome","in":"query","description":"Filter by outcome (pending, success, failure)","schema":{"type":"string","enum":["pending","success","failure"]}}],"responses":{"200":{"description":"Paginated list of journey sessions","headers":{"X-Request-ID":{"$ref":"#/components/headers/X-Request-ID"}}},"400":{"description":"Invalid outcome filter value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sessions/{id}":{"get":{"summary":"Get a single journey session","operationId":"getJourneySession","tags":["Sessions"],"parameters":[{"name":"id","in":"path","required":true,"description":"Journey session UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Journey session details including outcome and outcomeReason"},"404":{"description":"Session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/seller/sessions":{"post":{"summary":"Open a sell session for a buyer agent","operationId":"createSellSession","tags":["Seller"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"counterparty":{"type":"string","description":"Label for the buyer agent's principal (audit)"},"sessionKey":{"type":"string"},"title":{"type":"string"}}}}}},"responses":{"201":{"description":"Sell session created"},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope (commerce required)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"summary":"List sell sessions for the tenant","operationId":"listSellSessions","tags":["Seller"],"responses":{"200":{"description":"List of sell sessions","headers":{"X-Request-ID":{"$ref":"#/components/headers/X-Request-ID"}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/seller/sessions/{id}/messages":{"post":{"summary":"Send a buyer message and run one seller turn","operationId":"createSellSessionMessage","tags":["Seller"],"parameters":[{"name":"id","in":"path","required":true,"description":"Sell session UUID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"The buyer agent's message"},"merchantName":{"type":"string"},"catalogSummary":{"type":"string"},"requiredToClose":{"type":"string"},"allowCommit":{"type":"boolean","description":"When false, the seller quotes/builds but does not commit"}}}}}},"responses":{"200":{"description":"Seller reply with executed tool calls and token usage"},"404":{"description":"Sell session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Seller agent unavailable (no model key configured)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"summary":"Replay a sell session's turns","operationId":"listSellSessionMessages","tags":["Seller"],"parameters":[{"name":"id","in":"path","required":true,"description":"Sell session UUID","schema":{"type":"string"}}],"responses":{"200":{"description":"Ordered list of buyer and seller turns"},"404":{"description":"Sell session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/payment-methods":{"post":{"summary":"Add a payment method reference for an account","operationId":"addPaymentMethod","tags":["PaymentMethods"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["accountId"],"properties":{"accountId":{"type":"string"},"type":{"type":"string"},"lastFour":{"type":"string"}}}}}},"responses":{"201":{"description":"Payment method added (stub)"}}}},"/payment-methods/{id}/set-default":{"post":{"summary":"Set a payment method as the default for its account","operationId":"setDefaultPaymentMethod","tags":["PaymentMethods"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Default payment method set (stub)"}}}},"/webhooks/event-types":{"get":{"summary":"List all supported webhook event types that can be used in subscription `events` arrays","operationId":"listWebhookEventTypes","tags":["Webhooks"],"security":[{"ApiKeyAuth":[]},{"BearerAuth":[]}],"responses":{"200":{"description":"List of platform-supported event types","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEventType"}},"total":{"type":"integer"}}}}}}}}},"/webhooks":{"get":{"summary":"List webhook subscriptions","operationId":"listWebhooks","tags":["Webhooks"],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"name":"isActive","in":"query","description":"Filter by active status","schema":{"type":"boolean"}}],"responses":{"200":{"description":"Paginated list of webhook subscriptions","headers":{"X-Request-ID":{"$ref":"#/components/headers/X-Request-ID"}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Register a webhook subscription for event callbacks. Use `GET /webhooks/event-types` to discover available event type names. Subscribing to `*` receives all events.","operationId":"createWebhook","tags":["Webhooks"],"parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key to safely retry without creating duplicates","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri","description":"Public HTTPS endpoint that will receive POST requests."},"events":{"type":"array","items":{"type":"string"},"description":"Event type names to subscribe to. Use `*` for all events."}}}}}},"responses":{"201":{"description":"Webhook subscription created. The response includes the `secret` (shown once) used to verify payloads — see signature scheme in the description."},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{id}":{"get":{"summary":"Get webhook subscription details","operationId":"getWebhook","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Webhook subscription details"}}},"patch":{"summary":"Update a webhook subscription","operationId":"updateWebhook","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Webhook updated"}}},"delete":{"summary":"Delete a webhook subscription","operationId":"deleteWebhook","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Webhook deleted"}}}},"/webhooks/{id}/deliveries":{"get":{"summary":"List delivery history for a webhook subscription with optional status and time-range filtering","operationId":"listWebhookDeliveries","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook subscription ID"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"name":"status","in":"query","description":"Filter by delivery status (pending | retrying | delivered | dead_letter)","schema":{"type":"string","enum":["pending","retrying","delivered","dead_letter"]}},{"name":"since","in":"query","description":"Return deliveries created at or after this ISO 8601 timestamp","schema":{"type":"string","format":"date-time"}},{"name":"until","in":"query","description":"Return deliveries created at or before this ISO 8601 timestamp","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Paginated delivery history","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}}}},"404":{"description":"Webhook subscription not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{id}/deliveries/{deliveryId}":{"get":{"summary":"Get a single delivery record including request payload, response body, and attempt history","operationId":"getWebhookDelivery","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook subscription ID"},{"name":"deliveryId","in":"path","required":true,"schema":{"type":"string"},"description":"Delivery ID"}],"responses":{"200":{"description":"Delivery record","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{id}/deliveries/{deliveryId}/replay":{"post":{"summary":"Replay a delivery — re-enqueues the original payload for re-delivery. Works for any status including dead_letter.","operationId":"replayWebhookDelivery","tags":["Webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook subscription ID"},{"name":"deliveryId","in":"path","required":true,"schema":{"type":"string"},"description":"Delivery ID"}],"responses":{"202":{"description":"Replay enqueued. The delivery will be re-attempted asynchronously and its status updated."},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/preview/plan-change":{"post":{"summary":"Preview a plan change: returns effective date, proration, applicable business rule, and resolved price without executing the change","operationId":"previewPlanChange","tags":["Preview"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["subscriptionId","targetProductId"],"properties":{"subscriptionId":{"type":"string"},"targetProductId":{"type":"string"}}}}}},"responses":{"200":{"description":"Plan change preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewResponse"}}}},"404":{"description":"Subscription or product not found"}}}},"/preview/add-on":{"post":{"summary":"Preview adding an add-on to a subscription: returns effective date, co-term behavior, prorated first charge, and applicable business rule","operationId":"previewAddOn","tags":["Preview"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["subscriptionId","addOnProductId"],"properties":{"subscriptionId":{"type":"string"},"addOnProductId":{"type":"string"}}}}}},"responses":{"200":{"description":"Add-on preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewResponse"}}}},"404":{"description":"Subscription or product not found"}}}},"/preview/cancellation":{"post":{"summary":"Preview cancelling a subscription: returns effective date, refund/credit info, retention requirements, and applicable business rule","operationId":"previewCancellation","tags":["Preview"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["subscriptionId"],"properties":{"subscriptionId":{"type":"string"}}}}}},"responses":{"200":{"description":"Cancellation preview","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewResponse"}}}},"404":{"description":"Subscription not found"}}}},"/preview/order-total":{"post":{"summary":"Preview an order total: returns subtotal, tax, and shipping breakdown without creating an order. Calls the pluggable tax and shipping hooks configured for this tenant.","operationId":"previewOrderTotal","tags":["Preview"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"type":"object","required":["quantity","unitPriceCents"],"properties":{"productId":{"type":"string"},"name":{"type":"string"},"quantity":{"type":"integer","default":1},"unitPriceCents":{"type":"integer","minimum":0}}}},"currency":{"type":"string","default":"USD"},"shippingOptionId":{"type":"string"},"shippingAddress":{"$ref":"#/components/schemas/Address"},"taxAddress":{"$ref":"#/components/schemas/Address"},"customerContext":{"type":"object"}}}}}},"responses":{"200":{"description":"Order total preview with subtotal, tax, and shipping breakdown","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderTotalPreview"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/shipping-options":{"get":{"summary":"List available shipping options for a destination address. Returns rates from the pluggable shipping provider configured for this tenant.","operationId":"listShippingOptions","tags":["Shipping"],"parameters":[{"name":"currency","in":"query","schema":{"type":"string","default":"USD"}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"state","in":"query","schema":{"type":"string"}},{"name":"postalCode","in":"query","schema":{"type":"string"}},{"name":"city","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Available shipping options","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ShippingOption"}}}}}}},"401":{"description":"API key missing or invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/payments/{id}/refunds":{"post":{"summary":"Issue a refund against a successful payment session. Supports full refunds (default) and partial refunds via amountCents.","operationId":"issuePaymentRefund","tags":["Refunds"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Payment session ID"},{"name":"Idempotency-Key","in":"header","description":"Per-refund idempotency key. A retry with the same key + same body returns the original refund; same key + different body returns 409.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":1,"description":"Partial refund amount in cents. Omit to refund the full refundable balance."},"reason":{"type":"string","maxLength":500},"refundAll":{"type":"boolean","default":false,"description":"Explicitly refund the full remaining balance."}}}}}},"responses":{"200":{"description":"Replayed prior refund for the same Idempotency-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Refund"}}}},"201":{"description":"Refund issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Refund"}}}},"400":{"description":"Validation error or payment not refundable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Payment session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key reused with a different request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"summary":"List all refunds issued against a payment session","operationId":"listPaymentRefunds","tags":["Refunds"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Payment session ID"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"}],"responses":{"200":{"description":"Paginated list of refunds"},"404":{"description":"Payment session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/invoices/{id}/refunds":{"post":{"summary":"Issue a refund against the payment for an invoice. Targets the most recent successful payment session linked to this invoice.","operationId":"issueInvoiceRefund","tags":["Refunds"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Invoice ID (externalInvoiceId on the payment session)"},{"name":"Idempotency-Key","in":"header","description":"Per-refund idempotency key. A retry with the same key + same body returns the original refund; same key + different body returns 409.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"amountCents":{"type":"integer","minimum":1},"reason":{"type":"string","maxLength":500},"refundAll":{"type":"boolean","default":false}}}}}},"responses":{"200":{"description":"Replayed prior refund for the same Idempotency-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Refund"}}}},"201":{"description":"Refund issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Refund"}}}},"400":{"description":"Validation error or payment not refundable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No successful payment session found for this invoice","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Idempotency-Key reused with a different request body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"summary":"List all refunds issued against payments for an invoice","operationId":"listInvoiceRefunds","tags":["Refunds"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Invoice ID"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"}],"responses":{"200":{"description":"Paginated list of refunds"},"404":{"description":"No payment session in the caller's tenant references this invoice (anti-enumeration — see Task #1459)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/accounts/{id}/credits":{"post":{"summary":"Issue a credit to an account. Credits reduce the amount due on future payments when applied.","operationId":"issueCredit","tags":["Credits"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Account (organization) ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amountCents"],"properties":{"amountCents":{"type":"integer","minimum":1},"currency":{"type":"string","default":"USD","description":"3-letter ISO 4217 currency code"},"reason":{"type":"string","maxLength":500},"expiresAt":{"type":"string","format":"date-time","description":"ISO 8601 expiry timestamp. Omit for a non-expiring credit."}}}}}},"responses":{"201":{"description":"Credit issued","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Credit"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"summary":"List credits for an account","operationId":"listCredits","tags":["Credits"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Account ID"},{"name":"status","in":"query","schema":{"type":"string","enum":["active","applied","expired","cancelled"]}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"}],"responses":{"200":{"description":"Paginated list of credits"},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/accounts/{id}/credit-balance":{"get":{"summary":"Get the aggregate credit balance for an account — sum of all active, non-expired credits","operationId":"getCreditBalance","tags":["Credits"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Account ID"}],"responses":{"200":{"description":"Credit balance summary","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditBalance"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/accounts/{id}/credits/{creditId}/apply":{"post":{"summary":"Apply a credit (or a portion of it) to a payment session","operationId":"applyCredit","tags":["Credits"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Account ID"},{"name":"creditId","in":"path","required":true,"schema":{"type":"string"},"description":"Credit ID"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"paymentId":{"type":"string","description":"Payment session ID to apply the credit against. Omit to record an unallocated application."},"amountCents":{"type":"integer","minimum":1,"description":"Partial application amount. Omit to apply the full remaining balance."}}}}}},"responses":{"200":{"description":"Credit applied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Credit"}}}},"400":{"description":"Credit not active, expired, or exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Account, credit, or payment session not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pricing/resolve":{"get":{"summary":"Resolve the effective price for a product given customer context (segment, locale, partner, quantity). Returns the resolved price with a breakdown of pricing rules applied.","operationId":"resolvePricing","tags":["Pricing"],"parameters":[{"name":"productId","in":"query","required":true,"schema":{"type":"string"}},{"name":"segment","in":"query","schema":{"type":"string"}},{"name":"locale","in":"query","schema":{"type":"string"}},{"name":"partner","in":"query","schema":{"type":"string"}},{"name":"quantity","in":"query","schema":{"type":"integer","default":1}}],"responses":{"200":{"description":"Resolved pricing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingResolution"}}}},"404":{"description":"Product not found"}}}},"/users":{"get":{"summary":"List all users for the tenant","operationId":"listUsers","tags":["Admin - Users"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"name":"portalType","in":"query","description":"Filter by portal type (admin, customer, csr, partner)","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of users","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUser"}}}},"401":{"$ref":"#/components/schemas/Error"},"403":{"$ref":"#/components/schemas/Error"}}},"post":{"summary":"Create a new user","operationId":"createUser","tags":["Admin - Users"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","profileId"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":6,"description":"Required for password (database) sign-in tenants. Auth0-managed tenants must OMIT this — the user sets their own password via the email Auth0 sends; supplying one returns 400."},"profileId":{"type":"string","format":"uuid"},"portalType":{"type":"string"},"externalAccountId":{"type":"string"},"externalContactId":{"type":"string"},"isActive":{"type":"boolean"}}}}}},"responses":{"201":{"description":"User created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUser"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/users/{id}":{"get":{"summary":"Get user details","operationId":"getUser","tags":["Admin - Users"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"User details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUser"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update a user","operationId":"updateUser","tags":["Admin - Users"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string"},"profileId":{"type":"string"},"portalType":{"type":"string"},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"User updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUser"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a user","operationId":"deleteUser","tags":["Admin - Users"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"User deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/roles":{"get":{"summary":"List all roles (profiles) for the tenant","operationId":"listRoles","tags":["Admin - Roles"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"name":"role","in":"query","description":"Filter by role type (admin, customer, csr, partner)","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of roles","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Role"}}}}}},"post":{"summary":"Create a new role","operationId":"createRole","tags":["Admin - Roles"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","role"],"properties":{"name":{"type":"string"},"role":{"type":"string"},"description":{"type":"string"},"isActive":{"type":"boolean"},"permissions":{"type":"object"}}}}}},"responses":{"201":{"description":"Role created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Role"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/roles/{id}":{"get":{"summary":"Get role details","operationId":"getRole","tags":["Admin - Roles"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Role details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Role"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update a role","operationId":"updateRole","tags":["Admin - Roles"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"isActive":{"type":"boolean"},"permissions":{"type":"object"}}}}}},"responses":{"200":{"description":"Role updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Role"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a role (system roles cannot be deleted)","operationId":"deleteRole","tags":["Admin - Roles"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Role deleted"},"403":{"description":"System role — cannot delete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/roles/{id}/permissions":{"get":{"summary":"Get the permission set for a role","operationId":"getRolePermissions","tags":["Admin - Roles"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Permission object for this role"},"404":{"description":"Role not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update the permission set for a role","operationId":"updateRolePermissions","tags":["Admin - Roles"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"resources":{"type":"object"},"navigationGroups":{"type":"object"},"catalogGrants":{"type":"object"}}}}}},"responses":{"200":{"description":"Permissions updated"},"403":{"description":"Forbidden (system Administrator role)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Role not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pages":{"get":{"summary":"List all pages (portal, payment, storefront, checkout) for the tenant","operationId":"listAdminPages","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"name":"type","in":"query","description":"Filter by page type","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of pages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPage"}}}}}},"post":{"summary":"Create a new page","operationId":"createAdminPage","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","type"],"properties":{"name":{"type":"string"},"type":{"type":"string"},"slug":{"type":"string"},"pageContent":{"type":"object"}}}}}},"responses":{"201":{"description":"Page created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPage"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/pages/{id}":{"get":{"summary":"Get page details","operationId":"getAdminPage","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Page details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPage"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update a page","operationId":"updateAdminPage","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"slug":{"type":"string"},"pageContent":{"type":"object"}}}}}},"responses":{"200":{"description":"Page updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPage"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a page","operationId":"deleteAdminPage","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Page deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/custom-components":{"get":{"summary":"List all custom components for the tenant","operationId":"listCustomComponents","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"name":"context","in":"query","description":"Filter by editor context (payment, customer, portal, storefront, checkout, csr)","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of custom components","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomComponent"}}}}}},"post":{"summary":"Create a custom component","operationId":"createCustomComponent","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","componentType"],"properties":{"name":{"type":"string"},"displayName":{"type":"string"},"componentType":{"type":"string","enum":["code","template"]},"code":{"type":"string"},"category":{"type":"string"},"editorContexts":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"201":{"description":"Component created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomComponent"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/custom-components/{id}":{"get":{"summary":"Get custom component details","operationId":"getCustomComponent","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Component details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomComponent"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update a custom component","operationId":"updateCustomComponent","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"displayName":{"type":"string"},"code":{"type":"string"},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Component updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomComponent"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a custom component","operationId":"deleteCustomComponent","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Component deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/templates":{"get":{"summary":"List page templates","operationId":"listTemplates","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"name":"pageType","in":"query","description":"Filter by page type","schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of page templates","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageTemplate"}}}}}},"post":{"summary":"Create a page template","operationId":"createTemplate","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"pageType":{"type":"string"},"pageContent":{"type":"object"}}}}}},"responses":{"201":{"description":"Template created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageTemplate"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/templates/{id}":{"get":{"summary":"Get page template details","operationId":"getTemplate","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Template details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageTemplate"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update a page template (system templates cannot be modified)","operationId":"updateTemplate","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"},"pageContent":{"type":"object"},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Template updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PageTemplate"}}}},"403":{"description":"System template — cannot modify","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a page template (system templates cannot be deleted)","operationId":"deleteTemplate","tags":["Admin - Content"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Template deleted"},"403":{"description":"System template — cannot delete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/permissions":{"get":{"summary":"List the platform RBAC permission resources catalog — what resources can be granted, which role types they apply to, and the permission levels available","operationId":"listPermissions","tags":["Admin - Roles"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"role","in":"query","description":"Filter by role type (admin, customer, csr, partner) to see resources applicable to that role","schema":{"type":"string"}}],"responses":{"200":{"description":"Permission resource catalog","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"resource":{"type":"string","description":"Canonical permission resource id (e.g. users, pages, subscriptions)"},"roles":{"type":"array","items":{"type":"string"},"description":"Role types for which this resource is relevant"},"levels":{"type":"array","items":{"type":"string","enum":["none","view","edit"]}},"scopes":{"type":"array","items":{"type":"string","enum":["all","own","assigned"]}}}}},"meta":{"type":"object","properties":{"total":{"type":"integer"},"description":{"type":"string"}}},"requestId":{"type":"string"}}}}}}}}},"/status":{"get":{"summary":"Component-level health status suitable for status-page consumption. No auth required. Cached for 30 seconds.","operationId":"getStatus","tags":["Observability"],"security":[],"responses":{"200":{"description":"Component health status (may be operational, degraded, or incident)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/partners":{"get":{"summary":"List partner users with their profiles and commission structure","operationId":"listPartners","tags":["Admin - Partners"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"}],"responses":{"200":{"description":"Paginated list of partner users","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Partner"}}}}}}},"/partners/{userId}":{"get":{"summary":"Get a partner user with their profile","operationId":"getPartner","tags":["Admin - Partners"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Partner details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Partner"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/partners/{userId}/profile":{"put":{"summary":"Create or update a partner's profile","operationId":"upsertPartnerProfile","tags":["Admin - Partners"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"companyName":{"type":"string"},"contactName":{"type":"string"},"contactEmail":{"type":"string"},"tier":{"type":"string"},"commissionStructureId":{"type":"string"}}}}}},"responses":{"200":{"description":"Partner profile updated"},"404":{"description":"Partner not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/partners/{userId}/commissions":{"get":{"summary":"List commission records for a partner (performance read)","operationId":"listPartnerCommissions","tags":["Admin - Partners"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"}],"responses":{"200":{"description":"Paginated list of commission records"},"404":{"description":"Partner not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/partners/commission-structures":{"get":{"summary":"List all commission structures","operationId":"listCommissionStructures","tags":["Admin - Partners"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"}],"responses":{"200":{"description":"Paginated list of commission structures","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommissionStructure"}}}}}},"post":{"summary":"Create a commission structure","operationId":"createCommissionStructure","tags":["Admin - Partners"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","commissionType"],"properties":{"name":{"type":"string"},"commissionType":{"type":"string"},"rate":{"type":"number"},"flatAmount":{"type":"number"},"currency":{"type":"string"}}}}}},"responses":{"201":{"description":"Commission structure created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommissionStructure"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/partners/commission-structures/{id}":{"get":{"summary":"Get a commission structure","operationId":"getCommissionStructure","tags":["Admin - Partners"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Commission structure details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommissionStructure"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update a commission structure","operationId":"updateCommissionStructure","tags":["Admin - Partners"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"commissionType":{"type":"string"},"rate":{"type":"number"},"isActive":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Commission structure updated"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a commission structure","operationId":"deleteCommissionStructure","tags":["Admin - Partners"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Commission structure deleted"},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/audit-logs":{"get":{"summary":"Query audit logs with optional filtering by actor, resource, time range, and event type","operationId":"listAuditLogs","tags":["Admin - Audit"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"$ref":"#/components/parameters/SortDir"},{"name":"actor","in":"query","description":"Filter by user ID (actor) who performed the action","schema":{"type":"string"}},{"name":"resourceType","in":"query","description":"Filter by resource type (e.g. user, page, apiKey)","schema":{"type":"string"}},{"name":"action","in":"query","description":"Filter by action substring (e.g. user.create, subscription)","schema":{"type":"string"}},{"name":"since","in":"query","description":"Return logs created at or after this ISO 8601 timestamp","schema":{"type":"string","format":"date-time"}},{"name":"until","in":"query","description":"Return logs created at or before this ISO 8601 timestamp","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Paginated list of audit log entries, newest first by default","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditLog"}}}},"401":{"description":"API key required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api-keys":{"get":{"summary":"List API keys for the tenant (secrets are never returned in list responses)","operationId":"listApiKeys","tags":["Admin - API Keys"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"},{"name":"includeRevoked","in":"query","description":"Include revoked keys in the response","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"Paginated list of API key records (no secrets)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyRecord"}}}}}},"post":{"summary":"Create a new API key — the plaintext secret is returned only in this response","operationId":"createApiKey","tags":["Admin - API Keys"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"Idempotency-Key","in":"header","description":"Idempotency key to prevent duplicate key creation","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","enum":["read","commerce","admin"]},"default":["read"]},"rateLimitTier":{"type":"string","enum":["standard","premium","unlimited"],"default":"standard"},"expiresAt":{"type":"string","format":"date-time"}}}}}},"responses":{"201":{"description":"API key created — includes one-time plaintext secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreateResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api-keys/{id}/rotate":{"post":{"summary":"Rotate an API key — revokes the old key and creates a new one with the same name and scopes. The new plaintext secret is returned only in this response.","operationId":"rotateApiKey","tags":["Admin - API Keys"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"New API key issued — includes one-time plaintext secret","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreateResponse"}}}},"404":{"description":"Key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Key is already revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api-keys/{id}":{"delete":{"summary":"Revoke an API key","operationId":"revokeApiKey","tags":["Admin - API Keys"],"security":[{"ApiKeyAuth":[{"scope":"admin"}]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"API key revoked"},"404":{"description":"Key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/error-codes":{"get":{"summary":"Stable error code catalog. Returns every error code the v1 API can return, its HTTP status, description, and whether the error is retryable.","operationId":"getErrorCodes","tags":["Observability"],"security":[],"responses":{"200":{"description":"Complete error code catalog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCodes"}}}}}}},"/usage":{"get":{"summary":"Per-key API usage metrics (admin scope). Returns request counts, error counts, rate-limit hits, and latency broken down by route and 1-minute time bucket.","operationId":"getUsage","tags":["Observability"],"parameters":[{"name":"from","in":"query","description":"Start of the time window (ISO 8601). Defaults to 24 hours ago.","schema":{"type":"string","format":"date-time"}},{"name":"to","in":"query","description":"End of the time window (ISO 8601). Defaults to now.","schema":{"type":"string","format":"date-time"}},{"name":"apiKeyId","in":"query","description":"API key ID to filter. Defaults to the calling key. Pass `*` to see all keys on the tenant.","schema":{"type":"string"}},{"name":"route","in":"query","description":"Filter to a specific route pattern (e.g. `/accounts/:id`).","schema":{"type":"string"}}],"responses":{"200":{"description":"Usage summary with per-route and per-bucket breakdowns","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsageSummary"}}}},"401":{"description":"API key required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient scope (admin required)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}