{
  "openapi": "3.1.1",
  "info": {
    "title": "Billing prepaid API",
    "version": "0.4.0",
    "description": "Billing entrypoint only. Prepaid credits in units each product defines, priced in the currency of its catalog; usage is reported after it happens and any overrun becomes debt paid off by the next grant. Plans grant a monthly allowance that expires at the end of its period; paid plans are Stripe subscriptions. Isolated test/live products, served from a Cloudflare HTTPS root path. Public docs contain no tenant configuration. JSON bodies max 16 KiB except Stripe events. Live payment support requires environment-scoped credentials and a verified Stripe account binding; deployment and real-money acceptance are separate. Admin routes need an owner: a browser session of an account holding an address the deployment lists in BILLING_OWNERS, or that owner's MCP connector; cookie POST additionally requires matching Origin and X-CSRF-Token. Product Keys trust the product backend to bind users from authenticated identity."
  },
  "servers": [
    {
      "url": "/"
    }
  ],
  "paths": {
    "/healthz": {
      "get": {
        "operationId": "get__healthz",
        "summary": "Basic database read; not payment readiness",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/readyz": {
      "get": {
        "operationId": "get__readyz",
        "summary": "The ledger is open and answering; backup_ok is false while a backup alert stands",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ready": {
                      "type": "boolean"
                    },
                    "backup_ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ready",
                    "backup_ok"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/stripe/{product_id}": {
      "post": {
        "operationId": "post__webhooks_stripe_product_id_",
        "summary": "Verify Stripe signature and product environment; payload max 256 KiB",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [
          {
            "name": "product_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "Stripe-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "received": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "received"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/session": {
      "get": {
        "operationId": "get__auth_session",
        "summary": "Console session of an owner; 8 hour same-origin cookie; Secure on HTTPS",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "csrf": {
                      "type": "string"
                    },
                    "actor_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    }
                  },
                  "required": [
                    "csrf",
                    "actor_id"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-protected-resource/mcp": {
      "get": {
        "operationId": "get__well_known_oauth_protected_resource_mcp",
        "summary": "Protected resource metadata for /mcp (RFC 9728)",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "operationId": "get__well_known_oauth_authorization_server",
        "summary": "Authorization server metadata (RFC 8414)",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/oauth/register": {
      "post": {
        "operationId": "post__oauth_register",
        "summary": "Dynamic client registration (RFC 7591) for public clients without a metadata document",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/oauth/authorize": {
      "get": {
        "operationId": "get__oauth_authorize",
        "summary": "Start authorization (code flow with PKCE S256); redirects to the console's consent page",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "302": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "required": [],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/oauth/token": {
      "post": {
        "operationId": "post__oauth_token",
        "summary": "Exchange an authorization code or rotate a refresh token; form-encoded, RFC 6749 errors",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string"
                    },
                    "expires_in": {
                      "type": "integer"
                    },
                    "refresh_token": {
                      "type": "string"
                    },
                    "scope": {
                      "const": "billing"
                    }
                  },
                  "required": [
                    "access_token",
                    "token_type",
                    "expires_in",
                    "refresh_token",
                    "scope"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "post__mcp",
        "summary": "MCP Streamable HTTP with JSON responses: initialize, tools/list, tools/call. Tools are the owner's reads and writes, generated from the route tables, except product keys and saving Stripe settings",
        "tags": [
          "public"
        ],
        "security": [
          {
            "ConnectorToken": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "get__mcp",
        "summary": "Not supported: there is no server-initiated stream (405)",
        "tags": [
          "public"
        ],
        "security": [
          {
            "ConnectorToken": []
          }
        ],
        "parameters": [],
        "responses": {
          "405": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/capabilities": {
      "get": {
        "operationId": "get__v1_capabilities",
        "summary": "Current credential's actions; optional provider changes availability",
        "tags": [
          "either"
        ],
        "security": [
          {
            "ProductKey": []
          },
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Capabilities"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/catalog": {
      "get": {
        "operationId": "get__v1_catalog",
        "summary": "Current meter, the offers on sale and the plans on offer; offers are empty without a payment provider. Paid plans are sold as monthly subscriptions (POST /v1/users/{user}/subscription-checkouts)",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Catalog"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}": {
      "get": {
        "operationId": "get__v1_users_user_",
        "summary": "Account status; absent is 404",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/balance": {
      "get": {
        "operationId": "get__v1_users_user_balance",
        "summary": "Spendable balance excludes restricted sources; absent returns zero",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Balance"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/usage": {
      "post": {
        "operationId": "post__v1_users_user_usage",
        "summary": "Record usage that already happened; a repeated event_id answers its first result. Always recorded; allowed=false means stop",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UsageInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResult"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/close": {
      "post": {
        "operationId": "post__v1_users_user_close",
        "summary": "Close permanently; stop product work first. Closing a closed account answers it as it is",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloseInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/payment-profiles/detail": {
      "get": {
        "operationId": "get__v1_admin_payment_profiles_detail",
        "summary": "Read a local payment contact snapshot; browser session only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          },
          {
            "name": "kind",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "order",
                "invoice"
              ]
            }
          },
          {
            "name": "object_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/profile-sync": {
      "get": {
        "operationId": "get__v1_admin_profile_sync",
        "summary": "Profile synchronization state and payment enrichment backlog; browser session only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "post__v1_admin_profile_sync",
        "summary": "Pause and fence profile writers, or explicitly resume a reconciled generation; browser session only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "operation_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "action": {
                    "type": "string",
                    "enum": [
                      "pause",
                      "resume"
                    ]
                  },
                  "expected_generation": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  }
                },
                "required": [
                  "operation_id",
                  "action",
                  "expected_generation"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/user-profiles": {
      "get": {
        "operationId": "get__v1_admin_user_profiles",
        "summary": "Existing account directory with optional personal profiles and exact email/phone search; browser session only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          },
          {
            "name": "user",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "prefix",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "field",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "email",
                "phone"
              ]
            }
          },
          {
            "name": "query",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/user-profiles/detail": {
      "get": {
        "operationId": "get__v1_admin_user_profiles_detail",
        "summary": "Current product-supplied profile, without opening a ledger account; browser session only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          },
          {
            "name": "user",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/payment-profiles": {
      "get": {
        "operationId": "get__v1_admin_payment_profiles",
        "summary": "Local payment contact snapshots, scoped to this product; browser session only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          },
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "order",
                "invoice"
              ]
            }
          },
          {
            "name": "email",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/payment-profiles/backfill": {
      "post": {
        "operationId": "post__v1_admin_payment_profiles_backfill",
        "summary": "Enqueue at most 25 existing payment objects for contact enrichment without changing their financial state",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "order",
                      "invoice"
                    ]
                  },
                  "after": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  }
                },
                "required": [
                  "kind"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/payment-profiles/refresh": {
      "post": {
        "operationId": "post__v1_admin_payment_profiles_refresh",
        "summary": "Refresh payment contact data through the bounded enrichment worker, never re-settle payment",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "order",
                      "invoice"
                    ]
                  },
                  "object_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  }
                },
                "required": [
                  "kind",
                  "object_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/payment-profiles/clear": {
      "post": {
        "operationId": "post__v1_admin_payment_profiles_clear",
        "summary": "Clear locally retained payment contact data and suppress future automatic backfill; browser session only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "order",
                      "invoice"
                    ]
                  },
                  "object_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  }
                },
                "required": [
                  "kind",
                  "object_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/overview": {
      "get": {
        "operationId": "get__v1_admin_overview",
        "summary": "Administrator overview",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/stats": {
      "get": {
        "operationId": "get__v1_admin_stats",
        "summary": "The product's last 30 days: package money by currency (paid, refunded, net), orders awaiting payment, paying end users, subscriptions and paid money per day",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/users": {
      "get": {
        "operationId": "get__v1_admin_users",
        "summary": "Page through existing ledger accounts in the selected product, ordered by case-sensitive user ID; literal prefix or exact user (mutually exclusive). Reads settle due allowances and expiry for this page only, without creating accounts or calling the payment provider.",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          },
          {
            "name": "prefix",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "user",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 4096
            },
            "description": "Opaque cursor scoped to the product and search. Page size is 25."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AdminCustomers"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/users/{user}/balance": {
      "get": {
        "operationId": "get__v1_admin_users_user_balance",
        "summary": "Read a customer in the selected product environment",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/users/{user}/entries": {
      "get": {
        "operationId": "get__v1_admin_users_user_entries",
        "summary": "Read a customer in the selected product environment",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Use next_cursor verbatim. Pages contain at most 25 items."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/users/{user}/plan": {
      "get": {
        "operationId": "get__v1_admin_users_user_plan",
        "summary": "Read a customer's current plan, subscription and this period's allowance in the selected product environment",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerPlan"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/orders": {
      "get": {
        "operationId": "get__v1_admin_orders",
        "summary": "Administrator orders",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Use next_cursor verbatim. Pages contain at most 25 items."
          },
          {
            "name": "user",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "creating",
                "awaiting_payment",
                "fulfilled",
                "expired",
                "refunded"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 200,
                          "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/orders/{order}": {
      "get": {
        "operationId": "get__v1_admin_orders_order_",
        "summary": "Administrator orders/{id}, with its refunds",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "order",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/orders/{order}/refund": {
      "post": {
        "operationId": "post__v1_admin_orders_order_refund",
        "summary": "Owner refunds a fulfilled order, in one step; state is pending until Stripe settles it. An empty body refunds what is left of the order and withdraws the credits left (reference \"full\"); a partial refund names a refund_ref, an amount in minor units and optionally the credits to withdraw (by default the amount's share of the order's credits, rounded up; the last refund always takes all that is left). The reference identifies the refund: asking again answers it, different terms are refund_ref_conflict, and only a failed one may be retried. Only an owner, in the browser or through their own connector",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "order",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "refund_ref": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^(0|[1-9][0-9]{0,18})$",
                    "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                  },
                  "credits": {
                    "type": "string",
                    "pattern": "^(0|[1-9][0-9]{0,18})$",
                    "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "refund_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "order_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "state": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "succeeded",
                        "failed"
                      ]
                    }
                  },
                  "required": [
                    "refund_id",
                    "order_id",
                    "state"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/orders/{order}/external-refund": {
      "post": {
        "operationId": "post__v1_admin_orders_order_external_refund",
        "summary": "Owner settles money withdrawn at Stripe (a Dashboard refund or a lost dispute) on an order locked as partial_external_refund: external_total is the withdrawn total the owner saw on the order and confirms, credits optionally how many to withdraw (by default the share, rounded up). The rest is released. A different total now at Stripe is external_refund_changed; asking again with the same total answers the first",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "order",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "external_total": {
                    "type": "string",
                    "pattern": "^(0|[1-9][0-9]{0,18})$",
                    "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                  },
                  "credits": {
                    "type": "string",
                    "pattern": "^(0|[1-9][0-9]{0,18})$",
                    "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                  }
                },
                "required": [
                  "external_total"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/orders/{order}/keep": {
      "post": {
        "operationId": "post__v1_admin_orders_order_keep",
        "summary": "Owner keeps an order paid with a card from a region not sold to (ADR-0018), taking it off the attention list; refunding it is the other way",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "order",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/orders/{order}/recheck": {
      "post": {
        "operationId": "post__v1_admin_orders_order_recheck",
        "summary": "Owner re-reads this order and its pending refunds at Stripe now, as the hourly sweep would",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "order",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/offers": {
      "post": {
        "operationId": "post__v1_admin_offers",
        "summary": "Owner puts an offer on sale, or replaces the one under its sku; the currency must match the other offers on sale. A version is published once: the same version and content again answers the first result, other content is config_version_conflict",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "version": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "catalog": {
                    "$ref": "#/components/schemas/CatalogItem"
                  }
                },
                "required": [
                  "version",
                  "catalog"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sku": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "config_version": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    }
                  },
                  "required": [
                    "sku",
                    "config_version"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/offers/{sku}/retire": {
      "post": {
        "operationId": "post__v1_admin_offers_sku_retire",
        "summary": "Owner takes an offer off sale; existing orders and refunds keep their snapshot. An offer already off sale answers the same",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "sku",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sku": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "retired": {
                      "const": true
                    }
                  },
                  "required": [
                    "sku",
                    "retired"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/meter": {
      "post": {
        "operationId": "post__v1_admin_meter",
        "summary": "Owner changes the product's metric or rate (ADR-0016): a new meter version prices usage reported from now on; credits already granted keep their value and offers and plans are not converted. The same metric and rate again changes nothing",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "metric": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "credits_per_unit": {
                    "type": "string",
                    "pattern": "^[1-9][0-9]{0,18}$",
                    "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                  }
                },
                "required": [
                  "metric",
                  "credits_per_unit"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Meter"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/plans": {
      "post": {
        "operationId": "post__v1_admin_plans",
        "summary": "Owner publishes a plan, or replaces the definition under its sku from the next period on; price 0 is the free plan, at most one per product; the currency must match the offers and other plans. The same content again changes nothing",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sku": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "price": {
                    "type": "string",
                    "pattern": "^(0|[1-9][0-9]{0,18})$",
                    "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                  },
                  "currency": {
                    "type": "string",
                    "pattern": "^[a-z]{3}$",
                    "description": "ISO 4217 code in lowercase. A currency the Stripe account or a payment method does not accept is refused when the Checkout Session is created."
                  },
                  "credits": {
                    "type": "string",
                    "pattern": "^[1-9][0-9]{0,18}$",
                    "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                  },
                  "entitlements": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "The product's own JSON object (at most 4 KiB), returned as stored; Billing does not interpret it."
                  }
                },
                "required": [
                  "sku",
                  "name",
                  "price",
                  "currency",
                  "credits",
                  "entitlements"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Plan"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/plans/{sku}/retire": {
      "post": {
        "operationId": "post__v1_admin_plans_sku_retire",
        "summary": "Owner takes a plan off offer; allowances already granted run out as they would. A plan already retired answers the same",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "sku",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sku": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "retired": {
                      "const": true
                    }
                  },
                  "required": [
                    "sku",
                    "retired"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/exceptions": {
      "get": {
        "operationId": "get__v1_admin_exceptions",
        "summary": "Administrator exceptions",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Use next_cursor verbatim. Pages contain at most 25 items."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 200,
                          "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/audit-events": {
      "get": {
        "operationId": "get__v1_admin_audit_events",
        "summary": "Changes made to this product, newest first",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Use next_cursor verbatim. Pages contain at most 25 items."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 200,
                          "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/keys": {
      "get": {
        "operationId": "get__v1_admin_keys",
        "summary": "Owner lists the product's keys: name, id (the key's visible prefix), created and revoked times, and when each was first and last used (to the hour). Console only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "post__v1_admin_keys",
        "summary": "Owner issues a named product key. The secret is in this response only; the key never expires and stops working only when revoked. Console only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "secret": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "key_id",
                    "name",
                    "secret"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/keys/{key}/revoke": {
      "post": {
        "operationId": "post__v1_admin_keys_key_revoke",
        "summary": "Owner revokes a product key at once; requests with it are refused from then on. Console only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "key_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "revoked_at": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "key_id",
                    "revoked_at"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/test/users": {
      "post": {
        "operationId": "post__v1_test_users",
        "summary": "Owner creates disposable demo_ user, maximum 100 per instance; an existing one is answered as it is",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user_id": {
                    "type": "string",
                    "pattern": "^demo_[a-zA-Z0-9_-]{1,64}$"
                  }
                },
                "required": [
                  "user_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    }
                  },
                  "required": [
                    "user_id"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/test/users/{user}/grant": {
      "post": {
        "operationId": "post__v1_test_users_user_grant",
        "summary": "Owner grants a single synthetic package, never revenue; once per user, a second call answers the first grant",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/test/users/{user}/allowance": {
      "post": {
        "operationId": "post__v1_test_users_user_allowance",
        "summary": "Owner funds a demo_ user a monthly allowance that expires at expires_at (canonical UTC, in the future), never revenue; the same body again answers the same allowance. Test only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "credits": {
                    "type": "string",
                    "pattern": "^[1-9][0-9]{0,18}$",
                    "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                  },
                  "expires_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
                  }
                },
                "required": [
                  "credits",
                  "expires_at"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/test/users/{user}/purchase-sessions": {
      "post": {
        "operationId": "post__v1_test_users_user_purchase_sessions",
        "summary": "Owner opens a hosted top-up page for a demo_ user",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "return_path": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512,
                    "pattern": "^/(?!/)[^\\\\#\\u0000-\\u001f\\u007f]*$"
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "user_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
                    },
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "On the product's topup_origin when one is configured, otherwise on this service."
                    }
                  },
                  "required": [
                    "session_id",
                    "user_id",
                    "expires_at",
                    "url"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/test/users/{user}/subscription-checkouts": {
      "post": {
        "operationId": "post__v1_test_users_user_subscription_checkouts",
        "summary": "Owner starts a subscription checkout for a demo_ user, as a product would; test_clock (a Stripe test clock id) attaches the user's Stripe Customer to it when that customer is first created, so renewals can be simulated. Test only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "plan_sku": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "purchase_ref": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "test_clock": {
                    "type": "string",
                    "pattern": "^clock_[A-Za-z0-9]+$"
                  }
                },
                "required": [
                  "plan_sku",
                  "purchase_ref"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionReceipt"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/test/users/{user}/usage": {
      "post": {
        "operationId": "post__v1_test_users_user_usage",
        "summary": "Owner records synthetic usage for a demo_ user, as a product would",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UsageInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageResult"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/profile-sync": {
      "get": {
        "operationId": "get__v1_profile_sync",
        "summary": "The product's current profile synchronization generation and pause state",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/profile-sync/baseline": {
      "get": {
        "operationId": "get__v1_profile_sync_baseline",
        "summary": "Paged profile version and clear markers, without personal data; for explicit recovery reconciliation",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/user-profiles": {
      "post": {
        "operationId": "post__v1_user_profiles",
        "summary": "Replace a product user's complete optional profile under a monotonic version and matching generation; never opens or funds a ledger account",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "user_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "profile_revision": {
                    "type": "string",
                    "pattern": "^[1-9][0-9]{0,18}$",
                    "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                  },
                  "profile_sync_generation": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "profile": {
                    "type": "object",
                    "properties": {
                      "display_name": {
                        "anyOf": [
                          {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 100,
                            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "email": {
                        "anyOf": [
                          {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 254
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "phone": {
                        "anyOf": [
                          {
                            "type": "string",
                            "pattern": "^\\+[1-9][0-9]{6,14}$"
                          },
                          {
                            "type": "null"
                          }
                        ]
                      }
                    },
                    "required": [
                      "display_name",
                      "email",
                      "phone"
                    ],
                    "additionalProperties": false
                  }
                },
                "required": [
                  "user_id",
                  "profile_revision",
                  "profile_sync_generation",
                  "profile"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "409": {
            "description": "Profile pause, generation or revision conflict; the product must reconcile explicitly",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "retryable": {
                      "type": "boolean"
                    },
                    "user_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "profile_revision": {
                      "type": "string"
                    },
                    "profile_sync_generation": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    }
                  },
                  "required": [
                    "code",
                    "message",
                    "request_id",
                    "retryable",
                    "user_id",
                    "profile_revision",
                    "profile_sync_generation"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/checkouts": {
      "post": {
        "operationId": "post__v1_users_user_checkouts",
        "summary": "Create the purchase under its purchase_ref and answer with its Checkout URL; the same purchase_ref again answers the same order as it is now, or the same offer_changed refusal. 503 stripe_unavailable leaves it creating for a retry with the same purchase_ref",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutReceipt"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/purchase-sessions": {
      "post": {
        "operationId": "post__v1_users_user_purchase_sessions",
        "summary": "Open a hosted top-up page for this user: a 30-minute link with no product credential in it; each call opens a new link",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "return_path": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512,
                    "pattern": "^/(?!/)[^\\\\#\\u0000-\\u001f\\u007f]*$"
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "session_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "user_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
                    },
                    "url": {
                      "type": "string",
                      "format": "uri",
                      "description": "On the product's topup_origin when one is configured, otherwise on this service."
                    }
                  },
                  "required": [
                    "session_id",
                    "user_id",
                    "expires_at",
                    "url"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/plan": {
      "get": {
        "operationId": "get__v1_users_user_plan",
        "summary": "The user's current plan, its entitlements, the end of its period and this period's allowance. Like a balance read, it first expires what is due and grants the month's free allowance",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerPlan"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "post__v1_users_user_plan",
        "summary": "Change the plan of the user's active subscription (not past due, and not set to cancel at the period's end: 409 subscription_ending; resume it first). An upgrade (more credits per period) is charged for the rest of the period at once and applies only if that payment succeeds (409 plan_change_payment_failed otherwise); the difference in credits is granted at once, expiring with the period. A downgrade applies at once without refund; this period's credits stay and the next renewal grants the new plan's. A free plan is refused: cancel instead",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "plan_sku": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  }
                },
                "required": [
                  "plan_sku"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerPlan"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/subscription-checkouts": {
      "post": {
        "operationId": "post__v1_users_user_subscription_checkouts",
        "summary": "Start a paid plan: the subscription under its purchase_ref and its Checkout URL (card only, open for an hour); the same purchase_ref again answers the same subscription as it is now. A free or retired plan is refused, and so is a user with a subscription (409 subscription_exists: change it with POST .../plan); an open checkout of the user under another purchase_ref is expired first",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubscriptionCheckoutInput"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionReceipt"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/subscription/cancel": {
      "post": {
        "operationId": "post__v1_users_user_subscription_cancel",
        "summary": "Cancel the user's subscription at the end of its period: the plan stays until then, then the user is back on the free plan",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerPlan"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/subscription/resume": {
      "post": {
        "operationId": "post__v1_users_user_subscription_resume",
        "summary": "Take back a cancellation at the end of the period",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerPlan"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/billing-portal": {
      "post": {
        "operationId": "post__v1_users_user_billing_portal",
        "summary": "A Stripe Billing Portal link for the user (cards, invoices, cancellation), returning to return_path on the product's return origin. 409 billing_portal_not_configured until the portal is saved in the Stripe Dashboard",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "return_path": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512,
                    "pattern": "^/(?!/)[^\\\\#\\u0000-\\u001f\\u007f]*$"
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "required": [
                    "url"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/orders": {
      "get": {
        "operationId": "get__v1_users_user_orders",
        "summary": "User's orders",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Use next_cursor verbatim. Pages contain at most 25 items."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Orders"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/orders/{order}": {
      "get": {
        "operationId": "get__v1_users_user_orders_order_",
        "summary": "Checkout link and independently confirmed fulfillment state; an order still awaiting payment is first re-read at Stripe (at most every 10 seconds), so a success page polling it sees the payment without waiting for the webhook",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "order",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/history": {
      "get": {
        "operationId": "get__v1_users_user_history",
        "summary": "Purchases, usage, refunds and adjustments, newest first, each with the balance after it",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Use next_cursor verbatim. Pages contain at most 25 items."
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "purchase",
                "usage",
                "refund",
                "adjustment",
                "expiry"
              ]
            }
          },
          {
            "name": "grouped",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "true reads the usage reported under one group as one line, placed and identified by its first report: credits and units are the group's totals, balance_after and created_at are its latest report's, with reports and started_at."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/History"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/users/{user}/entries": {
      "get": {
        "operationId": "get__v1_users_user_entries",
        "summary": "Immutable entries; signed deltas, not balances",
        "tags": [
          "product"
        ],
        "security": [
          {
            "ProductKey": []
          }
        ],
        "parameters": [
          {
            "name": "user",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Use next_cursor verbatim. Pages contain at most 25 items."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Entries"
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/products": {
      "get": {
        "operationId": "get__v1_admin_products",
        "summary": "List the organization's products, archived ones included; works with none",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "post__v1_admin_products",
        "summary": "Owner creates an empty product. A name is unique per environment among products not deleted: the same name and input again answers that product, other input is product_name_taken",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "merchant_ref": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$",
                    "description": "A label in the product's identity, not a Stripe link. Omitted, it is the organization's id."
                  },
                  "environment": {
                    "type": "string",
                    "enum": [
                      "test",
                      "live"
                    ]
                  },
                  "config": {
                    "$ref": "#/components/schemas/Meter"
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/products/{product_id}/archive": {
      "post": {
        "operationId": "post__v1_admin_products_product_id_archive",
        "summary": "Owner archives a product; new checkouts are refused, history stays readable, and it is acted on only when named",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "product_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "product_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "archived": {
                      "type": "boolean"
                    },
                    "archived_at": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
                    }
                  },
                  "required": [
                    "product_id",
                    "archived",
                    "archived_at"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/products/{product_id}/delete": {
      "post": {
        "operationId": "post__v1_admin_products_product_id_delete",
        "summary": "Owner deletes a product (a tombstone; its ledger rows stay) with no unrevoked keys, no payments in flight and, if live, no payment within 120 days; the Stripe webhook endpoint Billing registered for it is removed",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "product_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "product_id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "name": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "deleted": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "product_id",
                    "name",
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/admin/stripe": {
      "get": {
        "operationId": "get__v1_admin_stripe",
        "summary": "Read redacted per-product Stripe configuration and revision",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "post__v1_admin_stripe",
        "summary": "Owner saves the product's Stripe settings in one step: checked with Stripe, the webhook registered when no signing secret is given, in force at once. Refused while orders are open or refunds pending, unless only the key of the same account, the payment methods or the top-up host change. Console only",
        "tags": [
          "admin"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "X-Billing-Product",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            },
            "description": "Select a product of the organization. It may be omitted only while the organization has a single product that is not archived: with none the answer is 409 no_product, with several 409 product_required. Product credentials cannot switch products."
          },
          {
            "name": "Origin",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Required with browser cookies"
          },
          {
            "name": "X-CSRF-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Required with browser cookies"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expected_revision": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "settings": {
                    "type": "object",
                    "properties": {
                      "account_id": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 200,
                        "pattern": "^[^\\u0000-\\u001f\\u007f]+$",
                        "description": "Omitted, read from secret_key on a first configuration and kept afterwards."
                      },
                      "secret_key": {
                        "type": "string",
                        "writeOnly": true,
                        "description": "Required until a configuration is in force."
                      },
                      "webhook_secret": {
                        "type": "string",
                        "writeOnly": true,
                        "description": "Omitted, Billing registers the webhook endpoint when saving and keeps its secret."
                      },
                      "return_origin": {
                        "type": "string"
                      },
                      "topup_origin": {
                        "type": "string",
                        "description": "The product's own host for the hosted top-up page, e.g. https://pay.example.com, with its DNS pointed at this service. One product per host."
                      },
                      "payment_methods": {
                        "type": "array",
                        "items": {
                          "type": "string",
                          "enum": [
                            "card",
                            "alipay",
                            "wechat_pay"
                          ]
                        }
                      },
                      "catalog": {
                        "$ref": "#/components/schemas/CatalogItem",
                        "description": "Legacy bootstrap offer; new products leave it out and publish offers instead."
                      }
                    },
                    "required": [],
                    "additionalProperties": false
                  }
                },
                "required": [
                  "expected_revision",
                  "settings"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/config": {
      "get": {
        "operationId": "get__auth_config",
        "summary": "Which sign-in methods this deployment offers",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/challenge": {
      "get": {
        "operationId": "get__auth_challenge",
        "summary": "A proof-of-work challenge to solve before asking for a code",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "challenge": {
                      "type": "string"
                    },
                    "bits": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "challenge",
                    "bits"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/code": {
      "post": {
        "operationId": "post__auth_code",
        "summary": "Send a one-time code. For sign-in the answer is the same whether or not the address may sign in, and only an owner's address is sent one",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "channel": {
                    "type": "string",
                    "enum": [
                      "email",
                      "sms"
                    ]
                  },
                  "address": {
                    "type": "string"
                  },
                  "purpose": {
                    "type": "string",
                    "enum": [
                      "login",
                      "bind"
                    ]
                  },
                  "work": {
                    "type": "object",
                    "properties": {
                      "challenge": {
                        "type": "string"
                      },
                      "nonce": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "challenge",
                      "nonce"
                    ],
                    "additionalProperties": false
                  }
                },
                "required": [
                  "channel",
                  "address",
                  "purpose"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/login": {
      "post": {
        "operationId": "post__auth_login",
        "summary": "Sign in with a code, or with a password and a bound email address or phone number. Only an owner may sign in (403 not_an_owner); an owner's listed email address signs in to a new account on first use",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "channel": {
                    "type": "string",
                    "enum": [
                      "email",
                      "sms"
                    ]
                  },
                  "address": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^[0-9]{6}$"
                  },
                  "login": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string"
                  }
                },
                "required": [
                  "channel",
                  "address",
                  "code",
                  "login",
                  "password"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/logout": {
      "post": {
        "operationId": "post__auth_logout",
        "summary": "End this browser session",
        "tags": [
          "public"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/logins": {
      "get": {
        "operationId": "get__auth_logins",
        "summary": "The signed-in person's sign-in methods",
        "tags": [
          "public"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/sign-ins": {
      "get": {
        "operationId": "get__auth_sign_ins",
        "summary": "Recent console sign-in attempts: the signed-in owner's own, and refused ones that named no account (kept 90 days)",
        "tags": [
          "public"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/logins/bind": {
      "post": {
        "operationId": "post__auth_logins_bind",
        "summary": "Bind a proven email address or phone number",
        "tags": [
          "public"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "channel": {
                    "type": "string",
                    "enum": [
                      "email",
                      "sms"
                    ]
                  },
                  "address": {
                    "type": "string"
                  },
                  "code": {
                    "type": "string",
                    "pattern": "^[0-9]{6}$"
                  }
                },
                "required": [
                  "channel",
                  "address",
                  "code"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/logins/remove": {
      "post": {
        "operationId": "post__auth_logins_remove",
        "summary": "Remove a sign-in method; neither the last one nor the last listed owner email address can be removed",
        "tags": [
          "public"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/password": {
      "post": {
        "operationId": "post__auth_password",
        "summary": "Set or change the password. Ends the person's other sessions and connectors",
        "tags": [
          "public"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "password": {
                    "type": "string"
                  }
                },
                "required": [
                  "password"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "ok"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/google/start": {
      "get": {
        "operationId": "get__auth_google_start",
        "summary": "Start signing in with Google (top-level navigation only); purpose login or bind",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "302": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "required": [],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/google/callback": {
      "get": {
        "operationId": "get__auth_google_callback",
        "summary": "Return from Google; redirects back to the page",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "303": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "required": [],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/wechat/start": {
      "get": {
        "operationId": "get__auth_wechat_start",
        "summary": "Start signing in with WeChat (top-level navigation only); purpose login or bind",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "302": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "required": [],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/wechat/callback": {
      "get": {
        "operationId": "get__auth_wechat_callback",
        "summary": "Return from the WeChat relay; redirects back to the page",
        "tags": [
          "public"
        ],
        "security": [],
        "parameters": [],
        "responses": {
          "303": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "required": [],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/connectors": {
      "get": {
        "operationId": "get__auth_connectors",
        "summary": "The signed-in person's live MCP connector connections, with the client's self-reported name and redirect host",
        "tags": [
          "public"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/connectors/{connection}/revoke": {
      "post": {
        "operationId": "post__auth_connectors_connection_revoke",
        "summary": "End one connector connection and its tokens at once",
        "tags": [
          "public"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "connection",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "revoked": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "id",
                    "revoked"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/connectors/requests/{request}": {
      "get": {
        "operationId": "get__auth_connectors_requests_request_",
        "summary": "A pending connector authorization: the client's self-reported name, its redirect host and the access it asks for",
        "tags": [
          "public"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "request",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/connectors/requests/{request}/approve": {
      "post": {
        "operationId": "post__auth_connectors_requests_request_approve",
        "summary": "Approve the connector as the signed-in owner; it then acts as that owner. Returns the client's redirect with a one-time code",
        "tags": [
          "public"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "request",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "redirect": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "redirect"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/connectors/requests/{request}/deny": {
      "post": {
        "operationId": "post__auth_connectors_requests_request_deny",
        "summary": "Decline the connector; returns the client's redirect with access_denied",
        "tags": [
          "public"
        ],
        "security": [
          {
            "PasswordCookie": []
          },
          {
            "SecurePasswordCookie": []
          }
        ],
        "parameters": [
          {
            "name": "request",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
            }
          },
          {
            "name": "Origin",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "redirect": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "redirect"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "default": {
            "description": "Structured error. 401 authentication; 403 scope/role/CSRF; 404 object absent or foreign; 409 conflict/closed/stale; 422 invalid input; 429 too many requests (honour Retry-After); 503 unavailable/recovery. Usage beyond the balance is recorded as debt, not refused. Retry only the original operation when appropriate.",
            "headers": {
              "Retry-After": {
                "description": "On a 429: seconds to wait before retrying (the end of the window for a per-session limit; 60 for the per-address limit at the edge). Absent when waiting would not help.",
                "schema": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ProductKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Backend product Key. Never put it in a browser; no grant/refund/admin authority."
      },
      "ConnectorToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "An MCP connector's one-hour access token from /oauth/token, accepted only at /mcp. Acts as the owner who approved the connector, for reads and writes, while that person is still an owner."
      },
      "PasswordCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "billing_auth.session_token",
        "description": "Loopback password session. Writes require Origin and X-CSRF-Token."
      },
      "SecurePasswordCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "__Secure-billing_auth.session_token",
        "description": "HTTPS password session. Writes require Origin and X-CSRF-Token."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          },
          "retryable": {
            "type": "boolean"
          }
        },
        "required": [
          "code",
          "message",
          "request_id",
          "retryable"
        ],
        "additionalProperties": false
      },
      "CatalogItem": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "fixed",
              "flexible"
            ]
          },
          "checkout": {
            "type": "object",
            "properties": {
              "display_name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
              },
              "logo_url": {
                "type": "string",
                "format": "uri",
                "pattern": "^https://",
                "maxLength": 2048
              },
              "icon_url": {
                "type": "string",
                "format": "uri",
                "pattern": "^https://",
                "maxLength": 2048
              },
              "background_color": {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              "button_color": {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              "locale": {
                "type": "string",
                "enum": [
                  "auto",
                  "bg",
                  "cs",
                  "da",
                  "de",
                  "el",
                  "en",
                  "en-GB",
                  "es",
                  "es-419",
                  "et",
                  "fi",
                  "fil",
                  "fr",
                  "fr-CA",
                  "hr",
                  "hu",
                  "id",
                  "it",
                  "ja",
                  "ko",
                  "lt",
                  "lv",
                  "ms",
                  "mt",
                  "nb",
                  "nl",
                  "pl",
                  "pt",
                  "pt-BR",
                  "ro",
                  "ru",
                  "sk",
                  "sl",
                  "sv",
                  "th",
                  "tr",
                  "vi",
                  "zh",
                  "zh-HK",
                  "zh-TW"
                ]
              }
            },
            "required": [],
            "additionalProperties": false,
            "minProperties": 1
          },
          "sku": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "amount": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "currency": {
            "type": "string",
            "pattern": "^[a-z]{3}$",
            "description": "ISO 4217 code in lowercase. A currency the Stripe account or a payment method does not accept is refused when the Checkout Session is created."
          },
          "credits": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "credits_per_unit": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "min_amount": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "max_amount": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "step": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          }
        },
        "required": [
          "sku",
          "amount",
          "currency",
          "credits"
        ],
        "additionalProperties": false
      },
      "QuotedCatalogItem": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "fixed",
              "flexible"
            ]
          },
          "checkout": {
            "type": "object",
            "properties": {
              "display_name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
              },
              "logo_url": {
                "type": "string",
                "format": "uri",
                "pattern": "^https://",
                "maxLength": 2048
              },
              "icon_url": {
                "type": "string",
                "format": "uri",
                "pattern": "^https://",
                "maxLength": 2048
              },
              "background_color": {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              "button_color": {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              "locale": {
                "type": "string",
                "enum": [
                  "auto",
                  "bg",
                  "cs",
                  "da",
                  "de",
                  "el",
                  "en",
                  "en-GB",
                  "es",
                  "es-419",
                  "et",
                  "fi",
                  "fil",
                  "fr",
                  "fr-CA",
                  "hr",
                  "hu",
                  "id",
                  "it",
                  "ja",
                  "ko",
                  "lt",
                  "lv",
                  "ms",
                  "mt",
                  "nb",
                  "nl",
                  "pl",
                  "pt",
                  "pt-BR",
                  "ro",
                  "ru",
                  "sk",
                  "sl",
                  "sv",
                  "th",
                  "tr",
                  "vi",
                  "zh",
                  "zh-HK",
                  "zh-TW"
                ]
              }
            },
            "required": [],
            "additionalProperties": false,
            "minProperties": 1
          },
          "sku": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "amount": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "currency": {
            "type": "string",
            "pattern": "^[a-z]{3}$",
            "description": "ISO 4217 code in lowercase. A currency the Stripe account or a payment method does not accept is refused when the Checkout Session is created."
          },
          "credits": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "credits_per_unit": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "min_amount": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "max_amount": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "step": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "offer_version": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "amount_decimals": {
            "type": "integer",
            "enum": [
              0,
              2,
              3
            ],
            "description": "Payment API scale: divide minor units by 10^amount_decimals. This is not necessarily ISO/Intl display precision (ISK/UGX use 2)."
          }
        },
        "required": [
          "sku",
          "amount",
          "currency",
          "credits",
          "offer_version",
          "amount_decimals"
        ],
        "additionalProperties": false
      },
      "Meter": {
        "type": "object",
        "properties": {
          "version": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "metric": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "credits_per_unit": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          }
        },
        "required": [
          "version",
          "metric",
          "credits_per_unit"
        ],
        "additionalProperties": false
      },
      "Plan": {
        "type": "object",
        "properties": {
          "sku": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "price": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]{0,18})$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "currency": {
            "type": "string",
            "pattern": "^[a-z]{3}$",
            "description": "ISO 4217 code in lowercase. A currency the Stripe account or a payment method does not accept is refused when the Checkout Session is created."
          },
          "credits": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "entitlements": {
            "type": "object",
            "additionalProperties": true,
            "description": "The product's own JSON object (at most 4 KiB), returned as stored; Billing does not interpret it."
          }
        },
        "required": [
          "sku",
          "name",
          "price",
          "currency",
          "credits",
          "entitlements"
        ],
        "additionalProperties": false
      },
      "AdminCustomers": {
        "type": "object",
        "properties": {
          "product_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "user_id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                },
                "account_state": {
                  "type": "string",
                  "enum": [
                    "active",
                    "closed"
                  ]
                },
                "balance": {
                  "type": "string",
                  "pattern": "^-?(0|[1-9][0-9]{0,18})$"
                },
                "debt": {
                  "type": "string",
                  "pattern": "^(0|[1-9][0-9]{0,18})$",
                  "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                },
                "restricted_credits": {
                  "type": "string",
                  "pattern": "^(0|[1-9][0-9]{0,18})$",
                  "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                },
                "plan": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "sku": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 200,
                          "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                        },
                        "name": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 200,
                          "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                        }
                      },
                      "required": [
                        "sku",
                        "name"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              },
              "required": [
                "user_id",
                "account_state",
                "balance",
                "debt",
                "restricted_credits",
                "plan"
              ],
              "additionalProperties": false
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 4096
              },
              {
                "type": "null"
              }
            ]
          },
          "read_at": {
            "type": "string",
            "format": "date-time",
            "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
          }
        },
        "required": [
          "product_id",
          "data",
          "has_more",
          "next_cursor",
          "read_at"
        ],
        "additionalProperties": false
      },
      "CustomerPlan": {
        "type": "object",
        "properties": {
          "plan": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Plan"
              },
              {
                "type": "null"
              }
            ],
            "description": "The user's current plan: the plan of a subscription that is active, trialing or past_due, otherwise the product's free plan; null when it has none."
          },
          "period_end": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
              },
              {
                "type": "null"
              }
            ],
            "description": "End of the current period: a subscription's billing period, or the end of the UTC month on the free plan."
          },
          "allowance": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "total": {
                    "type": "string",
                    "pattern": "^(0|[1-9][0-9]{0,18})$",
                    "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                  },
                  "remaining": {
                    "type": "string",
                    "pattern": "^(0|[1-9][0-9]{0,18})$",
                    "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                  },
                  "expires_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
                  }
                },
                "required": [
                  "total",
                  "remaining",
                  "expires_at"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ],
            "description": "This period's allowance: on a paid plan, what its paid invoices granted (an upgrade adds to it)."
          },
          "subscription": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200,
                    "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "trialing",
                      "past_due"
                    ]
                  },
                  "cancel_at_period_end": {
                    "type": "boolean"
                  },
                  "current_period_end": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
                  }
                },
                "required": [
                  "id",
                  "status",
                  "cancel_at_period_end",
                  "current_period_end"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "plan",
          "period_end",
          "allowance",
          "subscription"
        ],
        "additionalProperties": false
      },
      "SubscriptionCheckoutInput": {
        "type": "object",
        "properties": {
          "plan_sku": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "purchase_ref": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "return_path": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "pattern": "^/(?!/)[^\\\\#\\u0000-\\u001f\\u007f]*$"
          }
        },
        "required": [
          "plan_sku",
          "purchase_ref"
        ],
        "additionalProperties": false
      },
      "SubscriptionReceipt": {
        "type": "object",
        "properties": {
          "subscription_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "plan_sku": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "state": {
            "type": "string",
            "description": "checkout with checkout_url while the Checkout Session is open; checkout with a null checkout_url only after an earlier attempt lost Stripe's answer (retry with the same purchase_ref); checkout_expired after an hour unpaid; then the Stripe subscription status."
          },
          "checkout_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "subscription_id",
          "plan_sku",
          "state",
          "checkout_url"
        ],
        "additionalProperties": false
      },
      "Catalog": {
        "type": "object",
        "properties": {
          "config": {
            "$ref": "#/components/schemas/Meter"
          },
          "offers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/QuotedCatalogItem"
            }
          },
          "plans": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Plan"
            }
          },
          "payment_methods": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "card",
                "alipay",
                "wechat_pay"
              ]
            }
          },
          "environment": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ]
          }
        },
        "required": [
          "config",
          "offers",
          "plans",
          "payment_methods",
          "environment"
        ],
        "additionalProperties": false
      },
      "Capabilities": {
        "type": "object",
        "properties": {
          "version": {
            "const": "v1"
          },
          "release_version": {
            "const": "0.4.0"
          },
          "environment": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "test",
                  "live"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Null when no product is chosen."
          },
          "product_id": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200,
                "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
              },
              {
                "type": "null"
              }
            ],
            "description": "The product acted on; null when no product is chosen."
          },
          "actions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "version",
          "release_version",
          "environment",
          "actions"
        ],
        "additionalProperties": true
      },
      "Account": {
        "type": "object",
        "properties": {
          "account_state": {
            "type": "string",
            "enum": [
              "active",
              "closed"
            ]
          },
          "closed_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "account_state",
          "closed_at"
        ],
        "additionalProperties": false
      },
      "Balance": {
        "type": "object",
        "properties": {
          "account_state": {
            "type": "string",
            "enum": [
              "absent",
              "active",
              "closed"
            ]
          },
          "balance": {
            "type": "string",
            "pattern": "^-?(0|[1-9][0-9]{0,18})$"
          },
          "allowed": {
            "type": "boolean"
          },
          "debt": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]{0,18})$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "available": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]{0,18})$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "held": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]{0,18})$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "spent": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]{0,18})$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "reversed": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]{0,18})$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "expired": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]{0,18})$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "restricted_credits": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]{0,18})$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "source_key": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "purchase",
                    "test_grant",
                    "allowance"
                  ]
                },
                "total": {
                  "type": "string",
                  "pattern": "^(0|[1-9][0-9]{0,18})$",
                  "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                },
                "available": {
                  "type": "string",
                  "pattern": "^(0|[1-9][0-9]{0,18})$",
                  "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                },
                "restricted_credits": {
                  "type": "string",
                  "pattern": "^(0|[1-9][0-9]{0,18})$",
                  "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                },
                "held": {
                  "type": "string",
                  "pattern": "^(0|[1-9][0-9]{0,18})$",
                  "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                },
                "spent": {
                  "type": "string",
                  "pattern": "^(0|[1-9][0-9]{0,18})$",
                  "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                },
                "reversed": {
                  "type": "string",
                  "pattern": "^(0|[1-9][0-9]{0,18})$",
                  "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                },
                "expired": {
                  "type": "string",
                  "pattern": "^(0|[1-9][0-9]{0,18})$",
                  "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                },
                "expires_at": {
                  "anyOf": [
                    {
                      "type": "string",
                      "format": "date-time",
                      "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
                    },
                    {
                      "type": "null"
                    }
                  ],
                  "description": "When an allowance's unused credits expire; null for credits that never expire."
                },
                "restricted": {
                  "type": "boolean"
                },
                "loss_credits": {
                  "type": "string",
                  "pattern": "^(0|[1-9][0-9]{0,18})$",
                  "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                }
              },
              "required": [
                "source_key",
                "kind",
                "total",
                "available",
                "restricted_credits",
                "held",
                "spent",
                "reversed",
                "expired",
                "expires_at",
                "restricted",
                "loss_credits"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "account_state",
          "balance",
          "allowed",
          "debt",
          "available",
          "held",
          "spent",
          "reversed",
          "expired",
          "restricted_credits",
          "sources"
        ],
        "additionalProperties": false
      },
      "UsageInput": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "units": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]{0,18})$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "meter_version": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$",
            "description": "The catalog.config.version the units were measured in (ADR-0016). Another version than the current one is 409 meter_changed and records nothing; omitted, usage is priced by the current meter."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "String values only, at most 1 KB; recorded with the usage in history."
          },
          "group": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$",
            "description": "The call or session the usage belongs to. Part of the event's content. History read with grouped=true shows a group's reports as one line."
          }
        },
        "required": [
          "event_id",
          "units"
        ],
        "additionalProperties": false
      },
      "UsageResult": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "credits": {
            "type": "string",
            "pattern": "^(0|[1-9][0-9]{0,18})$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "balance": {
            "type": "string",
            "pattern": "^-?(0|[1-9][0-9]{0,18})$"
          },
          "allowed": {
            "type": "boolean"
          },
          "meter_version": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          }
        },
        "required": [
          "event_id",
          "credits",
          "balance",
          "allowed",
          "meter_version"
        ],
        "additionalProperties": false
      },
      "History": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "purchase",
                    "usage",
                    "refund",
                    "adjustment",
                    "expiry"
                  ]
                },
                "credits": {
                  "type": "string",
                  "pattern": "^-?(0|[1-9][0-9]{0,18})$"
                },
                "balance_after": {
                  "type": "string",
                  "pattern": "^-?(0|[1-9][0-9]{0,18})$"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
                },
                "event_id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                },
                "metadata": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  }
                },
                "note": {
                  "type": "string"
                },
                "units": {
                  "type": "string",
                  "pattern": "^(0|[1-9][0-9]{0,18})$",
                  "description": "Usage only: the units reported, summed over a grouped line's reports. Absent on a grouped line whose reports used different metrics."
                },
                "metric": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "pattern": "^[^\\u0000-\\u001f\\u007f]+$",
                  "description": "Usage only: the catalog.config.metric units was measured in. Absent for usage recorded before core schema 13 and on a grouped line whose reports used different metrics."
                },
                "group": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                },
                "reports": {
                  "type": "integer",
                  "description": "Grouped history only: how many reports the line sums."
                },
                "started_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Grouped history only: the group's first report."
                },
                "order": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 200,
                      "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                    },
                    "amount": {
                      "type": "string",
                      "pattern": "^(0|[1-9][0-9]{0,18})$",
                      "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
                    },
                    "currency": {
                      "type": "string",
                      "pattern": "^[a-z]{3}$",
                      "description": "ISO 4217 code in lowercase. A currency the Stripe account or a payment method does not accept is refused when the Checkout Session is created."
                    },
                    "state": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "amount",
                    "currency",
                    "state"
                  ],
                  "additionalProperties": false
                }
              },
              "required": [
                "id",
                "type",
                "credits",
                "balance_after",
                "created_at"
              ],
              "additionalProperties": false
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200,
                "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "CheckoutInput": {
        "type": "object",
        "properties": {
          "sku": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "purchase_ref": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "offer_version": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$",
            "description": "Catalog offer_version the payer confirmed. Supplied versions are checked only for new orders; stale quotes return a durable rejected receipt."
          },
          "return_path": {
            "type": "string",
            "minLength": 1,
            "maxLength": 512,
            "pattern": "^/(?!/)[^\\\\#\\u0000-\\u001f\\u007f]*$"
          },
          "amount": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "payment_method": {
            "type": "string",
            "enum": [
              "card",
              "alipay",
              "wechat_pay"
            ]
          }
        },
        "required": [
          "sku",
          "purchase_ref"
        ],
        "additionalProperties": false
      },
      "CloseInput": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "business_ref": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          }
        },
        "required": [
          "reason",
          "business_ref"
        ],
        "additionalProperties": false
      },
      "CheckoutReceipt": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "order_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200,
                "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
              },
              "state": {
                "type": "string",
                "enum": [
                  "creating",
                  "awaiting_payment",
                  "fulfilled",
                  "expired",
                  "refunded"
                ],
                "description": "The order's current state: awaiting_payment with checkout_url for a new order. A replay answers the same order as it is now. creating with a null checkout_url only after an earlier attempt lost Stripe's answer: retry with the same purchase_ref."
              },
              "checkout_url": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "uri"
                  },
                  {
                    "type": "null"
                  }
                ]
              }
            },
            "required": [
              "order_id",
              "state",
              "checkout_url"
            ],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "state": {
                "const": "rejected"
              },
              "reason": {
                "const": "offer_changed"
              }
            },
            "required": [
              "state",
              "reason"
            ],
            "additionalProperties": false
          }
        ]
      },
      "Order": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "fixed",
              "flexible"
            ]
          },
          "checkout": {
            "type": "object",
            "properties": {
              "display_name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100,
                "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
              },
              "logo_url": {
                "type": "string",
                "format": "uri",
                "pattern": "^https://",
                "maxLength": 2048
              },
              "icon_url": {
                "type": "string",
                "format": "uri",
                "pattern": "^https://",
                "maxLength": 2048
              },
              "background_color": {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              "button_color": {
                "type": "string",
                "pattern": "^#[0-9a-fA-F]{6}$"
              },
              "locale": {
                "type": "string",
                "enum": [
                  "auto",
                  "bg",
                  "cs",
                  "da",
                  "de",
                  "el",
                  "en",
                  "en-GB",
                  "es",
                  "es-419",
                  "et",
                  "fi",
                  "fil",
                  "fr",
                  "fr-CA",
                  "hr",
                  "hu",
                  "id",
                  "it",
                  "ja",
                  "ko",
                  "lt",
                  "lv",
                  "ms",
                  "mt",
                  "nb",
                  "nl",
                  "pl",
                  "pt",
                  "pt-BR",
                  "ro",
                  "ru",
                  "sk",
                  "sl",
                  "sv",
                  "th",
                  "tr",
                  "vi",
                  "zh",
                  "zh-HK",
                  "zh-TW"
                ]
              }
            },
            "required": [],
            "additionalProperties": false,
            "minProperties": 1
          },
          "sku": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "amount": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "currency": {
            "type": "string",
            "pattern": "^[a-z]{3}$",
            "description": "ISO 4217 code in lowercase. A currency the Stripe account or a payment method does not accept is refused when the Checkout Session is created."
          },
          "credits": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "credits_per_unit": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "min_amount": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "max_amount": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "step": {
            "type": "string",
            "pattern": "^[1-9][0-9]{0,18}$",
            "description": "Decimal integer string, at most 9223372036854775807. Cash is minor currency units; credits and usage are separate units."
          },
          "id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "product_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "account_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "user_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "purchase_ref": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
          },
          "state": {
            "type": "string",
            "enum": [
              "creating",
              "awaiting_payment",
              "fulfilled",
              "expired",
              "refunded"
            ]
          },
          "session_id": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200,
                "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
              },
              {
                "type": "null"
              }
            ]
          },
          "checkout_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ]
          },
          "payment_intent": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200,
                "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
              },
              {
                "type": "null"
              }
            ]
          },
          "exception": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
          },
          "fulfilled_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time",
                "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
              },
              {
                "type": "null"
              }
            ]
          },
          "offer_kind": {
            "type": "string",
            "enum": [
              "fixed",
              "flexible"
            ]
          },
          "payment_method": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "card",
                  "alipay",
                  "wechat_pay"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "return_path": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 512,
                "pattern": "^/(?!/)[^\\\\#\\u0000-\\u001f\\u007f]*$"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "sku",
          "amount",
          "currency",
          "credits",
          "id",
          "product_id",
          "account_id",
          "user_id",
          "purchase_ref",
          "state",
          "session_id",
          "checkout_url",
          "payment_intent",
          "exception",
          "created_at",
          "fulfilled_at"
        ],
        "additionalProperties": false
      },
      "Entries": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                },
                "business_key": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time",
                  "description": "Canonical UTC ISO, including milliseconds, e.g. 2026-09-12T00:00:00.000Z."
                },
                "source_key": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
                },
                "available": {
                  "type": "string",
                  "pattern": "^-?[0-9]+$"
                },
                "held": {
                  "type": "string",
                  "pattern": "^-?[0-9]+$"
                },
                "spent": {
                  "type": "string",
                  "pattern": "^-?[0-9]+$"
                },
                "reversed": {
                  "type": "string",
                  "pattern": "^-?[0-9]+$"
                },
                "expired": {
                  "type": "string",
                  "pattern": "^-?[0-9]+$"
                }
              },
              "required": [
                "id",
                "business_key",
                "created_at",
                "source_key",
                "available",
                "held",
                "spent",
                "reversed",
                "expired"
              ],
              "additionalProperties": false
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200,
                "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "additionalProperties": false
      },
      "Orders": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Order"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 200,
                "pattern": "^[^\\u0000-\\u001f\\u007f]+$"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "additionalProperties": false
      }
    }
  }
}
