frontend-sdk HTTP contracts
Supported HTTP operations, source validators, SDK companions and explicit OpenAPI schema limits.
Supported HTTP operations, source validators, SDK companions and explicit OpenAPI schema limits.
These HTTP contracts are an explicit supported subset, not the whole Core API. Prefer the SDK when it exposes the operation. Authentication schemes are alternatives, not interchangeable tokens. Use the documented consumer context or CLI exchange; never send a raw maker credential as a consumer token. Read the owning guides for permissions, confirmation and asynchronous completion.
GET /portal/businesses/{businessId}/me
OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.
SDK companion: client.me(...). Resolve its named inputs and outputs in the SDK declaration reference.
{
"limitation": "OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.",
"sdk": {
"usage": "client.me(...)",
"signature": "me(opts?: {\n signal?: AbortSignal;\n /** `null` omits the organization header without changing the shared\n * client selection; `undefined` uses that selection. */\n organizationId?: string | null;\n }): Promise<SubscriberContext | null>;",
"source": "packages/farthershore-js/dist/client.d.ts#L36",
"declarationName": "FartherShoreClient",
"page": "generated/frontend-sdk/root",
"typeReferences": [
{
"name": "AuditLogsResource",
"source": "packages/farthershore-js/dist/resources/account.d.ts#L142"
},
{
"name": "AuthResource",
"source": "packages/farthershore-js/dist/resources/auth.d.ts#L3"
},
{
"name": "BillingResource",
"source": "packages/farthershore-js/dist/resources/billing.d.ts#L13"
},
{
"name": "Bootstrap",
"source": "packages/farthershore-js/dist/types.d.ts#L294"
},
{
"name": "BusinessResource",
"source": "packages/farthershore-js/dist/resources/business.d.ts#L2"
},
{
"name": "ClientContext__d9dbf3313290",
"source": "packages/farthershore-js/dist/config.d.ts#L183"
},
{
"name": "CoreRequest",
"source": "packages/farthershore-js/dist/http.d.ts#L3"
},
{
"name": "EntitlementsResource",
"source": "packages/farthershore-js/dist/resources/entitlements.d.ts#L16"
},
{
"name": "FartherShoreApiError",
"source": "packages/farthershore-js/dist/errors/index.d.ts#L49"
},
{
"name": "KeysResource",
"source": "packages/farthershore-js/dist/resources/keys.d.ts#L3"
},
{
"name": "LegalAcceptance__cc2291cc0442",
"source": "packages/farthershore-js/dist/types.d.ts#L80"
},
{
"name": "ManagedIntegration",
"source": "packages/farthershore-js/dist/integrations.d.ts#L6"
},
{
"name": "NotificationsResource",
"source": "packages/farthershore-js/dist/resources/account.d.ts#L169"
},
{
"name": "ObservedLimitDeny__ff379deca309",
"source": "packages/farthershore-js/dist/errors/index.d.ts#L580"
},
{
"name": "OrganizationsResource",
"source": "packages/farthershore-js/dist/resources/account.d.ts#L3"
},
{
"name": "PlansResource",
"source": "packages/farthershore-js/dist/resources/plans.d.ts#L61"
},
{
"name": "PrefetchSurface__2b22bd2b6c45",
"source": "packages/farthershore-js/dist/client.d.ts#L24"
},
{
"name": "RateLimitSnapshot__934527ed940b",
"source": "packages/farthershore-js/dist/errors/index.d.ts#L8"
},
{
"name": "RbacResource",
"source": "packages/farthershore-js/dist/resources/account.d.ts#L65"
},
{
"name": "ResourcesResource",
"source": "packages/farthershore-js/dist/resources/resources.d.ts#L25"
},
{
"name": "RouteResource",
"source": "packages/farthershore-js/dist/resources/route.d.ts#L15"
},
{
"name": "SubscriberContext",
"source": "packages/farthershore-js/dist/types.d.ts#L897"
},
{
"name": "TeamResource",
"source": "packages/farthershore-js/dist/resources/account.d.ts#L13"
},
{
"name": "UsageLimitsResource",
"source": "packages/farthershore-js/dist/resources/usage-limits.d.ts#L3"
},
{
"name": "UsageResource",
"source": "packages/farthershore-js/dist/resources/usage.d.ts#L7"
}
]
}
}
OpenAPI metadata (incomplete):
{
"operationId": "getPortalConsumerContext",
"summary": "Return the signed-in consumer context for a product portal",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Consumer portal context. authSession is null except for a trusted site-shell cookie-authenticated test-persona session, where it contains only kind, personaId, userId, organizationId, displayName, and expiresAt (never a token, JWT ID, or raw claims).",
"content": {
"application/json": {
"schema": {
"allOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "object",
"required": [
"authSession"
],
"properties": {
"authSession": {
"oneOf": [
{
"type": "null"
},
{
"type": "object",
"additionalProperties": false,
"required": [
"kind",
"personaId",
"userId",
"organizationId",
"displayName",
"expiresAt"
],
"properties": {
"kind": {
"const": "test-persona"
},
"personaId": {
"type": "string"
},
"userId": {
"type": "string"
},
"organizationId": {
"type": [
"string",
"null"
]
},
"displayName": {
"type": [
"string",
"null"
]
},
"expiresAt": {
"type": "string",
"format": "date-time"
}
}
}
]
}
}
}
]
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
GET /portal/businesses/{businessId}/me/usage
OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.
SDK companion: client.usage.snapshot(...). Resolve its named inputs and outputs in the SDK declaration reference.
{
"limitation": "OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.",
"sdk": {
"usage": "client.usage.snapshot(...)",
"signature": "snapshot(range?: UsageRange, opts?: {\n signal?: AbortSignal;\n includeEvents?: boolean;\n }): Promise<UsageSnapshot>;",
"source": "packages/farthershore-js/dist/resources/usage.d.ts#L7",
"declarationName": "UsageResource",
"page": "generated/frontend-sdk/root",
"typeReferences": [
{
"name": "UsageEvent",
"source": "packages/farthershore-js/dist/types.d.ts#L679"
},
{
"name": "UsageRange",
"source": "packages/farthershore-js/dist/resources/usage.d.ts#L3"
},
{
"name": "UsageSnapshot",
"source": "packages/farthershore-js/dist/types.d.ts#L701"
},
{
"name": "UsageSummary",
"source": "packages/farthershore-js/dist/types.d.ts#L645"
}
]
}
}
OpenAPI metadata (incomplete):
{
"operationId": "getPortalConsumerUsage",
"summary": "Return usage for the signed-in consumer on a product portal",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Customer usage summary",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
GET /portal/businesses/{businessId}/me/resource-limit-usage
OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.
SDK companion: client.entitlements.resourceLimitUsage(...). Resolve its named inputs and outputs in the SDK declaration reference.
{
"limitation": "OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.",
"sdk": {
"usage": "client.entitlements.resourceLimitUsage(...)",
"signature": "resourceLimitUsage(): Promise<ResourceLimitUsageMap>;",
"source": "packages/farthershore-js/dist/resources/entitlements.d.ts#L16",
"declarationName": "EntitlementsResource",
"page": "generated/frontend-sdk/root",
"typeReferences": [
{
"name": "EntitlementSnapshot",
"source": "packages/farthershore-js/dist/resources/entitlements.d.ts#L3"
},
{
"name": "ResourceLimitUsageMap",
"source": "packages/farthershore-js/dist/resources/entitlements.d.ts#L15"
}
]
}
}
OpenAPI metadata (incomplete):
{
"operationId": "getPortalConsumerResourceLimitUsage",
"summary": "Return per-resource { limit, current } usage for the signed-in consumer's pinned plan",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Per-resource limit usage map — `{ [resourceKey]: { limit, current } }`; resources the plan doesn't declare are absent (= unlimited)",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
GET /portal/businesses/{businessId}/me/resources/{resource}/count
OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.
{
"limitation": "OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.",
"responseEvidence": {
"name": "ResourceUsage",
"source": "apps/core/src/services/resource-counts/resource-usage-service.ts#L35",
"declaration": "export type ResourceUsage = { count: number; cap: number | null };"
},
"note": "No typed SDK method for this HTTP read. Use the documented GET path and subjectId query parameter; there is no request body. ResourceUsage is the response body."
}
OpenAPI metadata (incomplete):
{
"operationId": "getPortalConsumerResourceCount",
"summary": "Return the authoritative { count, cap } for one declared counted resource on the signed-in consumer's subscription",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "resource",
"in": "path",
"required": true,
"description": "The declared counted-resource name.",
"schema": {
"type": "string"
}
},
{
"name": "subjectId",
"in": "query",
"required": false,
"description": "For subject-scoped resources: the subject id the count keys on.",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Authoritative resource usage — `{ count, cap }`; `cap` is null when uncapped. Empty subscription → `{ count: 0, cap: null }`.",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
GET /portal/businesses/{businessId}/me/api-keys
OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.
SDK companion: client.keys.list(...). Resolve its named inputs and outputs in the SDK declaration reference.
{
"limitation": "OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.",
"sdk": {
"usage": "client.keys.list(...)",
"signature": "list(opts?: {\n signal?: AbortSignal;\n }): Promise<ApiKey[]>;",
"source": "packages/farthershore-js/dist/resources/keys.d.ts#L3",
"declarationName": "KeysResource",
"page": "generated/frontend-sdk/root",
"typeReferences": [
{
"name": "ApiKey",
"source": "packages/farthershore-js/dist/types.d.ts#L347"
},
{
"name": "CreatedApiKey",
"source": "packages/farthershore-js/dist/types.d.ts#L375"
},
{
"name": "ServiceAccountsResource",
"source": "packages/farthershore-js/dist/resources/keys.d.ts#L53"
}
]
}
}
OpenAPI metadata (incomplete):
{
"operationId": "listPortalConsumerApiKeys",
"summary": "List consumer-scoped API keys for the signed-in user on a product portal",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Customer API keys",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
POST /portal/businesses/{businessId}/me/api-keys
OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.
SDK companion: client.keys.create(...). Resolve its named inputs and outputs in the SDK declaration reference.
{
"limitation": "OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.",
"sdk": {
"usage": "client.keys.create(...)",
"signature": "create(input?: {\n label?: string;\n scopes?: string[];\n roleKeys?: string[];\n restrictedPermissions?: string[];\n kind?: \"PERSONAL\";\n /** PERSONAL — mint FOR this member (their `Membership.id`); admin-gated. */\n memberId?: string;\n }): Promise<CreatedApiKey>;",
"source": "packages/farthershore-js/dist/resources/keys.d.ts#L3",
"declarationName": "KeysResource",
"page": "generated/frontend-sdk/root",
"typeReferences": [
{
"name": "ApiKey",
"source": "packages/farthershore-js/dist/types.d.ts#L347"
},
{
"name": "CreatedApiKey",
"source": "packages/farthershore-js/dist/types.d.ts#L375"
},
{
"name": "ServiceAccountsResource",
"source": "packages/farthershore-js/dist/resources/keys.d.ts#L53"
}
]
},
"requestValidator": {
"name": "createConsumerApiKeySchema",
"source": "apps/core/src/validation/portal-schemas.ts#L129",
"declaration": "export const createConsumerApiKeySchema = z.object({\n label: z.string().max(100, \"Label must be at most 100 characters\").optional(),\n environment: z.enum([\"production\", \"sandbox\"]).optional(),\n organizationId: z.string().uuid().optional(),\n /**\n * Phase 3 RBAC: optional scope strings restricting what the gateway will\n * permit on this key. Empty / missing array = god-mode (the historical\n * behaviour of every existing key). Each entry is validated against the\n * `<verb>:<resourcePattern>` grammar in the route handler before persist\n * — see `services/scope-matcher.ts`.\n */\n scopes: z.array(z.string()).max(50, \"At most 50 scopes per key\").optional(),\n /** UA-5 — live role bindings (SubscriberBusinessRole.roleKey refs). The\n * key's effective permission claim tracks the CURRENT role rows; role\n * edits reach the key without reprovisioning. */\n roleKeys: z\n .array(z.string().min(1).max(80))\n .max(20, \"At most 20 role bindings per key\")\n .optional(),\n /** UA-5 — optional Stripe-style narrowing of the bound roles' union. */\n restrictedPermissions: z\n .array(z.string().min(1).max(160))\n .max(100, \"At most 100 restricted permissions per key\")\n .optional(),\n /**\n * Consumer-principal (D2). Which subject the key credentials:\n * - `PERSONAL` (default) — a member key. Self-mint binds it to the caller;\n * passing `memberId` mints it FOR another member (admin-gated, D2a).\n * - `SERVICE` — an org-owned service key (admin-gated). Attach to an\n * existing account via `serviceAccountId`, or name a new one with\n * `serviceAccountName`.\n */\n kind: z.enum([\"PERSONAL\", \"SERVICE\"]).optional(),\n /** PERSONAL — the target member's stable Membership.id to bind the key to\n * (admin-gated when it isn't the caller's own). Omit for self-mint. */\n memberId: z.string().uuid().optional(),\n /** SERVICE — an existing ServiceAccount.id to attach the key to. */\n serviceAccountId: z.string().uuid().optional(),\n /** SERVICE — name for a new ServiceAccount when `serviceAccountId` is\n * omitted. */\n serviceAccountName: z\n .string()\n .max(100, \"Service account name must be at most 100 characters\")\n .optional(),\n});"
},
"note": "Use the SDK PERSONAL-key surface. Managed service credentials use the separate serviceAccounts lifecycle; the validator alone does not authorize every key kind."
}
OpenAPI metadata (incomplete):
{
"operationId": "createPortalConsumerApiKey",
"summary": "Create a consumer-scoped API key for the signed-in user on a product portal",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
},
"responses": {
"201": {
"description": "Customer API key created",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
DELETE /portal/businesses/{businessId}/me/api-keys/{keyId}
{
"operationId": "revokePortalConsumerApiKey",
"summary": "Revoke a consumer-scoped API key for the signed-in user on a product portal",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "keyId",
"in": "path",
"required": true,
"description": "Consumer API key identifier",
"schema": {
"type": "string"
}
}
],
"responses": {
"204": {
"description": "No content"
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
POST /portal/businesses/{businessId}/me/api-keys/{keyId}/rotate
OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.
SDK companion: client.keys.rotate(...). Resolve its named inputs and outputs in the SDK declaration reference.
{
"limitation": "OpenAPI uses GenericObject or GenericObjectArray here and does not fully specify the HTTP contract. These are documentation placeholders, not permission to send arbitrary fields. SDK signatures describe normalized SDK inputs and outputs, not exact wire response envelopes. Source validators specify structural inputs; route authorization and semantic checks still apply.",
"sdk": {
"usage": "client.keys.rotate(...)",
"signature": "rotate(keyId: string): Promise<CreatedApiKey>;",
"source": "packages/farthershore-js/dist/resources/keys.d.ts#L3",
"declarationName": "KeysResource",
"page": "generated/frontend-sdk/root",
"typeReferences": [
{
"name": "ApiKey",
"source": "packages/farthershore-js/dist/types.d.ts#L347"
},
{
"name": "CreatedApiKey",
"source": "packages/farthershore-js/dist/types.d.ts#L375"
},
{
"name": "ServiceAccountsResource",
"source": "packages/farthershore-js/dist/resources/keys.d.ts#L53"
}
]
},
"note": "Pass keyId as the path argument; no request body is required."
}
OpenAPI metadata (incomplete):
{
"operationId": "rotatePortalConsumerApiKey",
"summary": "Rotate a consumer-scoped API key — create a replacement then revoke the old one",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "keyId",
"in": "path",
"required": true,
"description": "Consumer API key identifier",
"schema": {
"type": "string"
}
}
],
"responses": {
"201": {
"description": "Rotated API key (new raw secret included)",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": true
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
GET /portal/businesses/{businessId}/me/service-accounts
{
"operationId": "listPortalServiceAccounts",
"summary": "List managed service accounts and their pending requests",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Maximum number of service accounts to return.",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 100
}
},
{
"name": "offset",
"in": "query",
"required": false,
"description": "Number of service accounts to skip.",
"schema": {
"type": "integer",
"minimum": 0,
"default": 0
}
}
],
"responses": {
"200": {
"description": "Managed service accounts",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"id",
"name",
"state",
"requestedPermissions",
"grantedPermissions",
"createdBy",
"approvedBy",
"createdAt",
"activatedAt",
"revokedAt",
"credentialApprovals"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"state": {
"type": "string",
"enum": [
"PENDING",
"ACTIVE"
]
},
"requestedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 100
},
"grantedPermissions": {
"type": "array",
"items": {
"type": "string"
}
},
"createdBy": {
"type": [
"string",
"null"
]
},
"approvedBy": {
"type": [
"string",
"null"
]
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"activatedAt": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"revokedAt": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"credentialApprovals": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"id",
"operation",
"requestedBy",
"requestedPermissions",
"excessPermissions",
"createdAt"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"operation": {
"type": "string",
"enum": [
"CREATE",
"UPDATE"
]
},
"requestedBy": {
"type": "string"
},
"requestedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 100
},
"excessPermissions": {
"type": "array",
"items": {
"type": "string"
}
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
}
}
}
}
},
"pagination": {
"type": "object",
"additionalProperties": false,
"required": [
"limit",
"offset",
"hasMore"
],
"properties": {
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100
},
"offset": {
"type": "integer",
"minimum": 0
},
"hasMore": {
"type": "boolean"
}
}
}
}
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
POST /portal/businesses/{businessId}/me/service-accounts
{
"operationId": "createPortalServiceAccount",
"summary": "Create or request approval for a managed service account",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "Idempotency-Key",
"in": "header",
"required": false,
"description": "Stable replay key for this provisioning request.",
"schema": {
"type": "string",
"minLength": 1
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"requestedPermissions"
],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 100
},
"requestedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 100
},
"scopes": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 50
},
"usageLimit": {
"type": "object",
"additionalProperties": false,
"required": [
"quantity",
"mode"
],
"properties": {
"quantity": {
"type": "string",
"pattern": "^[a-z0-9_]{1,64}$"
},
"mode": {
"type": "string",
"enum": [
"BLOCK",
"NOTIFY"
]
},
"notifyAtPct": {
"type": "number",
"minimum": 0.01,
"maximum": 1,
"description": "Required for NOTIFY usage limits and forbidden for BLOCK."
},
"limitUnits": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"limitCents": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
}
},
"oneOf": [
{
"required": [
"quantity",
"limitCents"
],
"properties": {
"quantity": {
"type": "string",
"const": "spend"
}
},
"not": {
"required": [
"limitUnits"
]
}
},
{
"required": [
"quantity",
"limitUnits"
],
"properties": {
"quantity": {
"type": "string",
"not": {
"const": "spend"
}
}
},
"not": {
"required": [
"limitCents"
]
}
}
],
"allOf": [
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "NOTIFY"
}
}
},
"then": {
"required": [
"notifyAtPct"
]
}
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "BLOCK"
}
}
},
"then": {
"not": {
"required": [
"notifyAtPct"
]
}
}
},
{
"if": {
"anyOf": [
{
"required": [
"limitUnits"
],
"properties": {
"limitUnits": {
"const": 0
}
}
},
{
"required": [
"limitCents"
],
"properties": {
"limitCents": {
"const": 0
}
}
}
]
},
"then": {
"properties": {
"mode": {
"const": "BLOCK"
}
}
}
}
]
}
}
}
}
}
},
"responses": {
"201": {
"description": "Service account created; secret returned once",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"status",
"serviceAccountId",
"apiKeyId",
"keyPrefix",
"plaintext",
"requestedPermissions",
"grantedPermissions"
],
"properties": {
"status": {
"type": "string",
"const": "ACTIVE"
},
"serviceAccountId": {
"type": "string",
"format": "uuid"
},
"grantedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 100
},
"apiKeyId": {
"type": "string",
"format": "uuid"
},
"keyPrefix": {
"type": "string"
},
"plaintext": {
"type": "string",
"writeOnly": true
},
"requestedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 100
}
}
}
}
}
},
"202": {
"description": "Service-account request pending approval; no secret exists",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"status",
"serviceAccountId",
"approvalId",
"requestedPermissions",
"grantedPermissions",
"excessPermissions",
"eligibleApproverIds"
],
"properties": {
"status": {
"type": "string",
"const": "PENDING"
},
"serviceAccountId": {
"type": "string",
"format": "uuid"
},
"approvalId": {
"type": "string",
"format": "uuid"
},
"requestedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 100
},
"grantedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 0
},
"excessPermissions": {
"type": "array",
"items": {
"type": "string"
}
},
"eligibleApproverIds": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"409": {
"description": "Conflict",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"422": {
"description": "Idempotency key was reused with a different request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
PATCH /portal/businesses/{businessId}/me/service-accounts/{serviceAccountId}
{
"operationId": "updatePortalServiceAccount",
"summary": "Update or request approval for a service-account grant snapshot",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "serviceAccountId",
"in": "path",
"required": true,
"description": "Managed service-account identifier",
"schema": {
"type": "string"
}
},
{
"name": "Idempotency-Key",
"in": "header",
"required": false,
"description": "Stable replay key for this provisioning request.",
"schema": {
"type": "string",
"minLength": 1
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"minProperties": 1,
"properties": {
"requestedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 100
},
"usageLimit": {
"anyOf": [
{
"type": "object",
"additionalProperties": false,
"required": [
"quantity",
"mode"
],
"properties": {
"quantity": {
"type": "string",
"pattern": "^[a-z0-9_]{1,64}$"
},
"mode": {
"type": "string",
"enum": [
"BLOCK",
"NOTIFY"
]
},
"notifyAtPct": {
"type": "number",
"minimum": 0.01,
"maximum": 1,
"description": "Required for NOTIFY usage limits and forbidden for BLOCK."
},
"limitUnits": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"limitCents": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
}
},
"oneOf": [
{
"required": [
"quantity",
"limitCents"
],
"properties": {
"quantity": {
"type": "string",
"const": "spend"
}
},
"not": {
"required": [
"limitUnits"
]
}
},
{
"required": [
"quantity",
"limitUnits"
],
"properties": {
"quantity": {
"type": "string",
"not": {
"const": "spend"
}
}
},
"not": {
"required": [
"limitCents"
]
}
}
],
"allOf": [
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "NOTIFY"
}
}
},
"then": {
"required": [
"notifyAtPct"
]
}
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "BLOCK"
}
}
},
"then": {
"not": {
"required": [
"notifyAtPct"
]
}
}
},
{
"if": {
"anyOf": [
{
"required": [
"limitUnits"
],
"properties": {
"limitUnits": {
"const": 0
}
}
},
{
"required": [
"limitCents"
],
"properties": {
"limitCents": {
"const": 0
}
}
}
]
},
"then": {
"properties": {
"mode": {
"const": "BLOCK"
}
}
}
}
]
},
{
"type": "null"
}
]
}
}
}
}
}
},
"responses": {
"200": {
"description": "Service-account snapshot updated",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"status",
"serviceAccountId",
"requestedPermissions",
"grantedPermissions"
],
"properties": {
"status": {
"type": "string",
"const": "ACTIVE"
},
"serviceAccountId": {
"type": "string",
"format": "uuid"
},
"grantedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 100
},
"requestedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 100
}
}
}
}
}
},
"202": {
"description": "Update pending approval; active snapshot is unchanged",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"status",
"serviceAccountId",
"approvalId",
"activePermissions",
"requestedPermissions",
"excessPermissions",
"eligibleApproverIds"
],
"properties": {
"status": {
"type": "string",
"const": "PENDING"
},
"serviceAccountId": {
"type": "string",
"format": "uuid"
},
"approvalId": {
"type": "string",
"format": "uuid"
},
"activePermissions": {
"type": "array",
"items": {
"type": "string"
}
},
"requestedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 100
},
"excessPermissions": {
"type": "array",
"items": {
"type": "string"
}
},
"eligibleApproverIds": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"409": {
"description": "Conflict",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"422": {
"description": "Idempotency key was reused with a different request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
POST /portal/businesses/{businessId}/me/service-accounts/{serviceAccountId}/rotate
{
"operationId": "rotatePortalServiceAccount",
"summary": "Rotate a managed service account and return its replacement secret once",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "serviceAccountId",
"in": "path",
"required": true,
"description": "Managed service-account identifier",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"properties": {}
}
}
}
},
"responses": {
"201": {
"description": "Service-account key rotated",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"status",
"serviceAccountId",
"revokedKeyId",
"apiKeyId",
"plaintext",
"grantedPermissions"
],
"properties": {
"status": {
"type": "string",
"const": "ACTIVE"
},
"serviceAccountId": {
"type": "string",
"format": "uuid"
},
"grantedPermissions": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"maxItems": 100
},
"revokedKeyId": {
"type": "string",
"format": "uuid"
},
"apiKeyId": {
"type": "string",
"format": "uuid"
},
"plaintext": {
"type": "string",
"writeOnly": true
}
}
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
POST /portal/businesses/{businessId}/me/service-accounts/{serviceAccountId}/revoke
{
"operationId": "revokePortalServiceAccount",
"summary": "Revoke a managed service account and all of its active keys",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "serviceAccountId",
"in": "path",
"required": true,
"description": "Managed service-account identifier",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"properties": {}
}
}
}
},
"responses": {
"204": {
"description": "No content"
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
GET /portal/businesses/{businessId}/me/usage-limits
{
"operationId": "listPortalUsageLimits",
"summary": "List subscriber-owned usage limits for the signed-in consumer",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"required": false,
"description": "Maximum number of usage limits to return.",
"schema": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"default": 100
}
},
{
"name": "offset",
"in": "query",
"required": false,
"description": "Number of usage limits to skip.",
"schema": {
"type": "integer",
"minimum": 0,
"default": 0
}
}
],
"responses": {
"200": {
"description": "Usage limits",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"data",
"pagination"
],
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"id",
"quantity",
"mode",
"period",
"createdBy",
"createdAt",
"updatedAt",
"scope"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"quantity": {
"type": "string",
"pattern": "^[a-z0-9_]{1,64}$"
},
"mode": {
"type": "string",
"enum": [
"BLOCK",
"NOTIFY"
]
},
"notifyAtPct": {
"type": "number",
"minimum": 0.01,
"maximum": 1,
"description": "Required for NOTIFY usage limits and forbidden for BLOCK."
},
"limitUnits": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"limitCents": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"scope": {
"type": "string",
"enum": [
"ORG",
"MEMBER",
"SERVICE_ACCOUNT"
]
},
"subjectId": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"period": {
"type": "string",
"const": "BILLING_PERIOD"
},
"ceiling": {
"type": "object",
"additionalProperties": false,
"properties": {
"limitUnits": {
"type": "integer",
"minimum": 0
},
"limitCents": {
"type": "integer",
"minimum": 0
}
},
"description": "The builder's own per-billing-period ceiling on this quantity, when the plan declares one. Read-only."
},
"effectiveWindow": {
"type": "object",
"additionalProperties": false,
"required": [
"strategy",
"periodSeconds"
],
"properties": {
"strategy": {
"type": "string",
"enum": [
"fixed_window",
"sliding_window"
]
},
"periodSeconds": {
"type": "integer",
"minimum": 1
}
},
"description": "Read-only: how the limit is accounted at the edge. `sliding_window` means the ceiling is a rolling horizon of `periodSeconds` rather than one that resets at the billing-period boundary. Builder-owned; not writable."
},
"createdBy": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
},
"allOf": [
{
"oneOf": [
{
"required": [
"quantity",
"limitCents"
],
"properties": {
"quantity": {
"type": "string",
"const": "spend"
}
},
"not": {
"required": [
"limitUnits"
]
}
},
{
"required": [
"quantity",
"limitUnits"
],
"properties": {
"quantity": {
"type": "string",
"not": {
"const": "spend"
}
}
},
"not": {
"required": [
"limitCents"
]
}
}
]
},
{
"oneOf": [
{
"required": [
"scope"
],
"properties": {
"scope": {
"type": "string",
"const": "ORG"
}
},
"not": {
"required": [
"subjectId"
]
}
},
{
"required": [
"scope",
"subjectId"
],
"properties": {
"scope": {
"type": "string",
"const": "MEMBER"
}
}
},
{
"required": [
"scope",
"subjectId"
],
"properties": {
"scope": {
"type": "string",
"const": "SERVICE_ACCOUNT"
}
}
}
]
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "NOTIFY"
}
}
},
"then": {
"required": [
"notifyAtPct"
]
}
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "BLOCK"
}
}
},
"then": {
"not": {
"required": [
"notifyAtPct"
]
}
}
},
{
"if": {
"anyOf": [
{
"required": [
"limitUnits"
],
"properties": {
"limitUnits": {
"const": 0
}
}
},
{
"required": [
"limitCents"
],
"properties": {
"limitCents": {
"const": 0
}
}
}
]
},
"then": {
"properties": {
"mode": {
"const": "BLOCK"
}
}
}
}
]
}
},
"pagination": {
"type": "object",
"additionalProperties": false,
"required": [
"limit",
"offset",
"hasMore"
],
"properties": {
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 100
},
"offset": {
"type": "integer",
"minimum": 0
},
"hasMore": {
"type": "boolean"
}
}
}
}
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
POST /portal/businesses/{businessId}/me/usage-limits
{
"operationId": "createPortalUsageLimit",
"summary": "Create a subscriber-owned usage limit",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"quantity",
"mode",
"scope"
],
"properties": {
"quantity": {
"type": "string",
"pattern": "^[a-z0-9_]{1,64}$"
},
"mode": {
"type": "string",
"enum": [
"BLOCK",
"NOTIFY"
]
},
"notifyAtPct": {
"type": "number",
"minimum": 0.01,
"maximum": 1,
"description": "Required for NOTIFY usage limits and forbidden for BLOCK."
},
"limitUnits": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"limitCents": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"scope": {
"type": "string",
"enum": [
"ORG",
"MEMBER",
"SERVICE_ACCOUNT"
]
},
"subjectId": {
"type": "string",
"minLength": 1,
"maxLength": 128
}
},
"allOf": [
{
"oneOf": [
{
"required": [
"quantity",
"limitCents"
],
"properties": {
"quantity": {
"type": "string",
"const": "spend"
}
},
"not": {
"required": [
"limitUnits"
]
}
},
{
"required": [
"quantity",
"limitUnits"
],
"properties": {
"quantity": {
"type": "string",
"not": {
"const": "spend"
}
}
},
"not": {
"required": [
"limitCents"
]
}
}
]
},
{
"oneOf": [
{
"required": [
"scope"
],
"properties": {
"scope": {
"type": "string",
"const": "ORG"
}
},
"not": {
"required": [
"subjectId"
]
}
},
{
"required": [
"scope",
"subjectId"
],
"properties": {
"scope": {
"type": "string",
"const": "MEMBER"
}
}
},
{
"required": [
"scope",
"subjectId"
],
"properties": {
"scope": {
"type": "string",
"const": "SERVICE_ACCOUNT"
}
}
}
]
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "NOTIFY"
}
}
},
"then": {
"required": [
"notifyAtPct"
]
}
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "BLOCK"
}
}
},
"then": {
"not": {
"required": [
"notifyAtPct"
]
}
}
},
{
"if": {
"anyOf": [
{
"required": [
"limitUnits"
],
"properties": {
"limitUnits": {
"const": 0
}
}
},
{
"required": [
"limitCents"
],
"properties": {
"limitCents": {
"const": 0
}
}
}
]
},
"then": {
"properties": {
"mode": {
"const": "BLOCK"
}
}
}
}
]
}
}
}
},
"responses": {
"201": {
"description": "Usage limit created",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"id",
"quantity",
"mode",
"period",
"createdBy",
"createdAt",
"updatedAt",
"scope"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"quantity": {
"type": "string",
"pattern": "^[a-z0-9_]{1,64}$"
},
"mode": {
"type": "string",
"enum": [
"BLOCK",
"NOTIFY"
]
},
"notifyAtPct": {
"type": "number",
"minimum": 0.01,
"maximum": 1,
"description": "Required for NOTIFY usage limits and forbidden for BLOCK."
},
"limitUnits": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"limitCents": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"scope": {
"type": "string",
"enum": [
"ORG",
"MEMBER",
"SERVICE_ACCOUNT"
]
},
"subjectId": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"period": {
"type": "string",
"const": "BILLING_PERIOD"
},
"ceiling": {
"type": "object",
"additionalProperties": false,
"properties": {
"limitUnits": {
"type": "integer",
"minimum": 0
},
"limitCents": {
"type": "integer",
"minimum": 0
}
},
"description": "The builder's own per-billing-period ceiling on this quantity, when the plan declares one. Read-only."
},
"effectiveWindow": {
"type": "object",
"additionalProperties": false,
"required": [
"strategy",
"periodSeconds"
],
"properties": {
"strategy": {
"type": "string",
"enum": [
"fixed_window",
"sliding_window"
]
},
"periodSeconds": {
"type": "integer",
"minimum": 1
}
},
"description": "Read-only: how the limit is accounted at the edge. `sliding_window` means the ceiling is a rolling horizon of `periodSeconds` rather than one that resets at the billing-period boundary. Builder-owned; not writable."
},
"createdBy": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
},
"allOf": [
{
"oneOf": [
{
"required": [
"quantity",
"limitCents"
],
"properties": {
"quantity": {
"type": "string",
"const": "spend"
}
},
"not": {
"required": [
"limitUnits"
]
}
},
{
"required": [
"quantity",
"limitUnits"
],
"properties": {
"quantity": {
"type": "string",
"not": {
"const": "spend"
}
}
},
"not": {
"required": [
"limitCents"
]
}
}
]
},
{
"oneOf": [
{
"required": [
"scope"
],
"properties": {
"scope": {
"type": "string",
"const": "ORG"
}
},
"not": {
"required": [
"subjectId"
]
}
},
{
"required": [
"scope",
"subjectId"
],
"properties": {
"scope": {
"type": "string",
"const": "MEMBER"
}
}
},
{
"required": [
"scope",
"subjectId"
],
"properties": {
"scope": {
"type": "string",
"const": "SERVICE_ACCOUNT"
}
}
}
]
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "NOTIFY"
}
}
},
"then": {
"required": [
"notifyAtPct"
]
}
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "BLOCK"
}
}
},
"then": {
"not": {
"required": [
"notifyAtPct"
]
}
}
},
{
"if": {
"anyOf": [
{
"required": [
"limitUnits"
],
"properties": {
"limitUnits": {
"const": 0
}
}
},
{
"required": [
"limitCents"
],
"properties": {
"limitCents": {
"const": 0
}
}
}
]
},
"then": {
"properties": {
"mode": {
"const": "BLOCK"
}
}
}
}
]
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"409": {
"description": "Conflict",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
GET /portal/businesses/{businessId}/me/usage-limits/{limitId}
{
"operationId": "getPortalUsageLimit",
"summary": "Get one subscriber-owned usage limit",
"description": "Requires usage_limit:read. Without subscription-wide mutation authority, members can fetch organization limits and their own member limit rows only; other members' rows return 404.",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "limitId",
"in": "path",
"required": true,
"description": "Usage-limit identifier",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Usage limit",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"id",
"quantity",
"mode",
"period",
"createdBy",
"createdAt",
"updatedAt",
"scope"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"quantity": {
"type": "string",
"pattern": "^[a-z0-9_]{1,64}$"
},
"mode": {
"type": "string",
"enum": [
"BLOCK",
"NOTIFY"
]
},
"notifyAtPct": {
"type": "number",
"minimum": 0.01,
"maximum": 1,
"description": "Required for NOTIFY usage limits and forbidden for BLOCK."
},
"limitUnits": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"limitCents": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"scope": {
"type": "string",
"enum": [
"ORG",
"MEMBER",
"SERVICE_ACCOUNT"
]
},
"subjectId": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"period": {
"type": "string",
"const": "BILLING_PERIOD"
},
"ceiling": {
"type": "object",
"additionalProperties": false,
"properties": {
"limitUnits": {
"type": "integer",
"minimum": 0
},
"limitCents": {
"type": "integer",
"minimum": 0
}
},
"description": "The builder's own per-billing-period ceiling on this quantity, when the plan declares one. Read-only."
},
"effectiveWindow": {
"type": "object",
"additionalProperties": false,
"required": [
"strategy",
"periodSeconds"
],
"properties": {
"strategy": {
"type": "string",
"enum": [
"fixed_window",
"sliding_window"
]
},
"periodSeconds": {
"type": "integer",
"minimum": 1
}
},
"description": "Read-only: how the limit is accounted at the edge. `sliding_window` means the ceiling is a rolling horizon of `periodSeconds` rather than one that resets at the billing-period boundary. Builder-owned; not writable."
},
"createdBy": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
},
"allOf": [
{
"oneOf": [
{
"required": [
"quantity",
"limitCents"
],
"properties": {
"quantity": {
"type": "string",
"const": "spend"
}
},
"not": {
"required": [
"limitUnits"
]
}
},
{
"required": [
"quantity",
"limitUnits"
],
"properties": {
"quantity": {
"type": "string",
"not": {
"const": "spend"
}
}
},
"not": {
"required": [
"limitCents"
]
}
}
]
},
{
"oneOf": [
{
"required": [
"scope"
],
"properties": {
"scope": {
"type": "string",
"const": "ORG"
}
},
"not": {
"required": [
"subjectId"
]
}
},
{
"required": [
"scope",
"subjectId"
],
"properties": {
"scope": {
"type": "string",
"const": "MEMBER"
}
}
},
{
"required": [
"scope",
"subjectId"
],
"properties": {
"scope": {
"type": "string",
"const": "SERVICE_ACCOUNT"
}
}
}
]
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "NOTIFY"
}
}
},
"then": {
"required": [
"notifyAtPct"
]
}
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "BLOCK"
}
}
},
"then": {
"not": {
"required": [
"notifyAtPct"
]
}
}
},
{
"if": {
"anyOf": [
{
"required": [
"limitUnits"
],
"properties": {
"limitUnits": {
"const": 0
}
}
},
{
"required": [
"limitCents"
],
"properties": {
"limitCents": {
"const": 0
}
}
}
]
},
"then": {
"properties": {
"mode": {
"const": "BLOCK"
}
}
}
}
]
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
PUT /portal/businesses/{businessId}/me/usage-limits/{limitId}
{
"operationId": "updatePortalUsageLimit",
"summary": "Update a subscriber-owned usage limit",
"description": "Updates a usage-limit row across the subscription. This is an all-mutation operation and requires subscription-wide usage_limit:update authority, not just own-row read authority.",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "limitId",
"in": "path",
"required": true,
"description": "Usage-limit identifier",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"minProperties": 1,
"properties": {
"limitUnits": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"limitCents": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"mode": {
"type": "string",
"enum": [
"BLOCK",
"NOTIFY"
]
},
"notifyAtPct": {
"anyOf": [
{
"type": "number",
"minimum": 0.01,
"maximum": 1
},
{
"type": "null"
}
],
"description": "Required for NOTIFY usage limits and forbidden for BLOCK."
}
},
"not": {
"required": [
"limitUnits",
"limitCents"
]
},
"allOf": [
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "NOTIFY"
}
}
},
"then": {
"required": [
"notifyAtPct"
],
"properties": {
"notifyAtPct": {
"type": "number"
}
}
}
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "BLOCK"
}
}
},
"then": {
"properties": {
"notifyAtPct": {
"type": "null"
}
}
}
},
{
"if": {
"allOf": [
{
"anyOf": [
{
"required": [
"limitUnits"
],
"properties": {
"limitUnits": {
"const": 0
}
}
},
{
"required": [
"limitCents"
],
"properties": {
"limitCents": {
"const": 0
}
}
}
]
},
{
"required": [
"mode"
]
}
]
},
"then": {
"properties": {
"mode": {
"const": "BLOCK"
}
}
}
}
]
}
}
}
},
"responses": {
"200": {
"description": "Usage limit updated",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"id",
"quantity",
"mode",
"period",
"createdBy",
"createdAt",
"updatedAt",
"scope"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"quantity": {
"type": "string",
"pattern": "^[a-z0-9_]{1,64}$"
},
"mode": {
"type": "string",
"enum": [
"BLOCK",
"NOTIFY"
]
},
"notifyAtPct": {
"type": "number",
"minimum": 0.01,
"maximum": 1,
"description": "Required for NOTIFY usage limits and forbidden for BLOCK."
},
"limitUnits": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"limitCents": {
"type": "integer",
"minimum": 0,
"maximum": 2147483647
},
"scope": {
"type": "string",
"enum": [
"ORG",
"MEMBER",
"SERVICE_ACCOUNT"
]
},
"subjectId": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"period": {
"type": "string",
"const": "BILLING_PERIOD"
},
"ceiling": {
"type": "object",
"additionalProperties": false,
"properties": {
"limitUnits": {
"type": "integer",
"minimum": 0
},
"limitCents": {
"type": "integer",
"minimum": 0
}
},
"description": "The builder's own per-billing-period ceiling on this quantity, when the plan declares one. Read-only."
},
"effectiveWindow": {
"type": "object",
"additionalProperties": false,
"required": [
"strategy",
"periodSeconds"
],
"properties": {
"strategy": {
"type": "string",
"enum": [
"fixed_window",
"sliding_window"
]
},
"periodSeconds": {
"type": "integer",
"minimum": 1
}
},
"description": "Read-only: how the limit is accounted at the edge. `sliding_window` means the ceiling is a rolling horizon of `periodSeconds` rather than one that resets at the billing-period boundary. Builder-owned; not writable."
},
"createdBy": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"updatedAt": {
"type": "string",
"format": "date-time"
}
},
"allOf": [
{
"oneOf": [
{
"required": [
"quantity",
"limitCents"
],
"properties": {
"quantity": {
"type": "string",
"const": "spend"
}
},
"not": {
"required": [
"limitUnits"
]
}
},
{
"required": [
"quantity",
"limitUnits"
],
"properties": {
"quantity": {
"type": "string",
"not": {
"const": "spend"
}
}
},
"not": {
"required": [
"limitCents"
]
}
}
]
},
{
"oneOf": [
{
"required": [
"scope"
],
"properties": {
"scope": {
"type": "string",
"const": "ORG"
}
},
"not": {
"required": [
"subjectId"
]
}
},
{
"required": [
"scope",
"subjectId"
],
"properties": {
"scope": {
"type": "string",
"const": "MEMBER"
}
}
},
{
"required": [
"scope",
"subjectId"
],
"properties": {
"scope": {
"type": "string",
"const": "SERVICE_ACCOUNT"
}
}
}
]
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "NOTIFY"
}
}
},
"then": {
"required": [
"notifyAtPct"
]
}
},
{
"if": {
"required": [
"mode"
],
"properties": {
"mode": {
"const": "BLOCK"
}
}
},
"then": {
"not": {
"required": [
"notifyAtPct"
]
}
}
},
{
"if": {
"anyOf": [
{
"required": [
"limitUnits"
],
"properties": {
"limitUnits": {
"const": 0
}
}
},
{
"required": [
"limitCents"
],
"properties": {
"limitCents": {
"const": 0
}
}
}
]
},
"then": {
"properties": {
"mode": {
"const": "BLOCK"
}
}
}
}
]
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
DELETE /portal/businesses/{businessId}/me/usage-limits/{limitId}
{
"operationId": "deletePortalUsageLimit",
"summary": "Delete a subscriber-owned usage limit",
"description": "Deletes a usage-limit row across the subscription. This is an all-mutation operation and requires subscription-wide usage_limit:delete authority, not just own-row read authority.",
"tags": [
"portal-customer"
],
"security": [
{
"consumerBearerAuth": []
},
{
"siteShellServiceJwt": [],
"personaSessionCookie": []
}
],
"parameters": [
{
"name": "businessId",
"in": "path",
"required": true,
"description": "Business identifier",
"schema": {
"type": "string"
}
},
{
"name": "limitId",
"in": "path",
"required": true,
"description": "Usage-limit identifier",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "Usage limit deleted",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"id",
"deleted"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"deleted": {
"type": "boolean",
"const": true
}
}
}
}
}
},
"401": {
"description": "Unauthorized",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"403": {
"description": "Forbidden",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
},
"404": {
"description": "Not found",
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"error"
],
"properties": {
"error": {
"type": "object",
"additionalProperties": false,
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"details": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
}
}
}
}
}
{
"browserBearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT",
"description": "Browser session token forwarded by the frontend"
},
"consumerBearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT",
"description": "Consumer portal session token forwarded by the frontend"
},
"cliUserSessionBearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "cli_access JWT",
"description": "Short-lived CLI access JWT exchanged from a live user-bound fscli_ session. Eligibility is revalidated from current organization membership and role grants."
},
"makerTokenAccessBearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "cli_access JWT",
"description": "Short-lived CLI access JWT exchanged from an organization-scoped mk_ MakerToken. Authority is limited to the token's frozen exact grants and business scope."
},
"rawCliCredentialBearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "fscli_ session or mk_ MakerToken",
"description": "Raw CLI credential accepted only by exchange, organization discovery, and CLI-session revocation infrastructure."
},
"serviceJwtBearer": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "Ed25519 service JWT",
"description": "Short-lived Farther Shore service identity JWT for internal machine calls"
},
"siteShellServiceJwt": {
"type": "apiKey",
"in": "header",
"name": "x-fs-service-jwt",
"description": "Short-lived Farther Shore site-shell service JWT with proxy:trust scope"
},
"localPreviewProxyLease": {
"type": "apiKey",
"in": "header",
"name": "x-fs-local-persona-proxy",
"description": "CLI-process-only local-preview lease (fslpl_…) attached by the `farthershore frontend dev|preview --live` loopback proxy together with `x-fs-local-preview-origin` (the exact http://localhost:<port> origin it was issued for). Verified against Core's lease store and pinned to one persona/environment/business/portal host; a raw header pair without a live lease grants nothing. Never sent by browser code."
},
"personaSessionCookie": {
"type": "apiKey",
"in": "cookie",
"name": "__Host-fs_persona_session",
"description": "Host-only HttpOnly persona session cookie. Accepted only through a trusted boundary: together with the hosted site shell's service JWT, or through the CLI's localhost preview proxy presenting a verified local-preview lease (x-fs-local-persona-proxy + x-fs-local-preview-origin). Never as a bearer."
}
}