{
  "components": {
    "schemas": {
      "AccountBillingResponse": {
        "properties": {
          "billing_authorized": {
            "title": "Billing Authorized",
            "type": "boolean"
          },
          "collection_available": {
            "title": "Collection Available",
            "type": "boolean"
          },
          "next_invoice": {
            "$ref": "#/components/schemas/NextInvoiceInfo"
          },
          "object": {
            "const": "account.billing",
            "default": "account.billing",
            "title": "Object",
            "type": "string"
          },
          "plan": {
            "$ref": "#/components/schemas/MetaPlanInfo"
          },
          "subscription": {
            "$ref": "#/components/schemas/MetaSubscriptionInfo"
          },
          "usage": {
            "items": {
              "$ref": "#/components/schemas/UsageMeterInfo"
            },
            "title": "Usage",
            "type": "array"
          }
        },
        "required": [
          "plan",
          "subscription",
          "usage",
          "next_invoice",
          "collection_available",
          "billing_authorized"
        ],
        "title": "AccountBillingResponse",
        "type": "object"
      },
      "ActivationResponse": {
        "properties": {
          "completed": {
            "title": "Completed",
            "type": "integer"
          },
          "domain_verified": {
            "title": "Domain Verified",
            "type": "boolean"
          },
          "has_price": {
            "title": "Has Price",
            "type": "boolean"
          },
          "has_product": {
            "title": "Has Product",
            "type": "boolean"
          },
          "has_test_payment": {
            "title": "Has Test Payment",
            "type": "boolean"
          },
          "has_webhook": {
            "title": "Has Webhook",
            "type": "boolean"
          },
          "mollie_connected": {
            "title": "Mollie Connected",
            "type": "boolean"
          },
          "object": {
            "const": "onboarding.activation",
            "default": "onboarding.activation",
            "title": "Object",
            "type": "string"
          },
          "ready_for_live": {
            "title": "Ready For Live",
            "type": "boolean"
          },
          "steps": {
            "items": {
              "$ref": "#/components/schemas/ActivationStepInfo"
            },
            "title": "Steps",
            "type": "array"
          },
          "total": {
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "steps",
          "completed",
          "total",
          "ready_for_live",
          "mollie_connected",
          "has_product",
          "has_price",
          "domain_verified",
          "has_test_payment",
          "has_webhook"
        ],
        "title": "ActivationResponse",
        "type": "object"
      },
      "ActivationStepInfo": {
        "properties": {
          "done": {
            "title": "Done",
            "type": "boolean"
          },
          "key": {
            "title": "Key",
            "type": "string"
          }
        },
        "required": [
          "key",
          "done"
        ],
        "title": "ActivationStepInfo",
        "type": "object"
      },
      "ApiKeyCreateRequest": {
        "additionalProperties": false,
        "properties": {
          "label": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Label"
          },
          "scopes": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "minItems": 1,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Scopes"
          }
        },
        "title": "ApiKeyCreateRequest",
        "type": "object"
      },
      "ApiKeyResponse": {
        "properties": {
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Label"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "object": {
            "const": "api_key",
            "default": "api_key",
            "title": "Object",
            "type": "string"
          },
          "prefix": {
            "title": "Prefix",
            "type": "string"
          },
          "revoked_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Revoked At"
          },
          "scopes": {
            "items": {
              "type": "string"
            },
            "title": "Scopes",
            "type": "array"
          },
          "secret": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Secret"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "prefix",
          "label",
          "scopes",
          "last_used_at",
          "revoked_at"
        ],
        "title": "ApiKeyResponse",
        "type": "object"
      },
      "AttentionItemInfo": {
        "description": "One \"needs attention\" row.\n\n``key`` is the stable identity the console keys its icon off;\neverything else is copy the server owns so a new condition can ship\nwithout a frontend release.",
        "properties": {
          "body": {
            "title": "Body",
            "type": "string"
          },
          "count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Count"
          },
          "cta": {
            "title": "Cta",
            "type": "string"
          },
          "href": {
            "title": "Href",
            "type": "string"
          },
          "key": {
            "title": "Key",
            "type": "string"
          },
          "severity": {
            "enum": [
              "bad",
              "warn",
              "info"
            ],
            "title": "Severity",
            "type": "string"
          },
          "title": {
            "title": "Title",
            "type": "string"
          }
        },
        "required": [
          "key",
          "severity",
          "title",
          "body",
          "cta",
          "href"
        ],
        "title": "AttentionItemInfo",
        "type": "object"
      },
      "AttentionResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/AttentionItemInfo"
            },
            "title": "Data",
            "type": "array"
          },
          "object": {
            "const": "account.attention",
            "default": "account.attention",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "AttentionResponse",
        "type": "object"
      },
      "AuditLogResponse": {
        "properties": {
          "action": {
            "title": "Action",
            "type": "string"
          },
          "actor_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Actor Id"
          },
          "actor_type": {
            "title": "Actor Type",
            "type": "string"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "ip_address": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ip Address"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "metadata": {
            "additionalProperties": true,
            "title": "Metadata",
            "type": "object"
          },
          "object": {
            "const": "audit_log",
            "default": "audit_log",
            "title": "Object",
            "type": "string"
          },
          "resource_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resource Id"
          },
          "resource_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Resource Type"
          },
          "user_agent": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Agent"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "actor_type",
          "actor_id",
          "action",
          "resource_type",
          "resource_id",
          "metadata",
          "ip_address",
          "user_agent"
        ],
        "title": "AuditLogResponse",
        "type": "object"
      },
      "BillingPortalSessionCreate": {
        "additionalProperties": false,
        "properties": {
          "deliver_email": {
            "default": false,
            "title": "Deliver Email",
            "type": "boolean"
          },
          "return_url": {
            "format": "uri",
            "maxLength": 2083,
            "minLength": 1,
            "title": "Return Url",
            "type": "string"
          },
          "subscription_id": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Subscription Id",
            "type": "string"
          }
        },
        "required": [
          "subscription_id",
          "return_url"
        ],
        "title": "BillingPortalSessionCreate",
        "type": "object"
      },
      "BillingPortalSessionResponse": {
        "properties": {
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "customer_id": {
            "title": "Customer Id",
            "type": "string"
          },
          "expires_at": {
            "title": "Expires At",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "object": {
            "const": "billing_portal.session",
            "default": "billing_portal.session",
            "title": "Object",
            "type": "string"
          },
          "return_url": {
            "title": "Return Url",
            "type": "string"
          },
          "subscription_id": {
            "title": "Subscription Id",
            "type": "string"
          },
          "token": {
            "title": "Token",
            "type": "string"
          },
          "url": {
            "title": "Url",
            "type": "string"
          }
        },
        "required": [
          "id",
          "livemode",
          "subscription_id",
          "customer_id",
          "token",
          "url",
          "return_url",
          "created",
          "expires_at"
        ],
        "title": "BillingPortalSessionResponse",
        "type": "object"
      },
      "BillingPortalSessionRevokeResponse": {
        "description": "Response for ``POST /v1/billing_portal/sessions/{id}/revoke``.\n\nDistinct from :class:`BillingPortalSessionResponse` because revoke\nhas no raw token to surface (we never persist it; the row carries\nonly its peppered hash). Returning the mint shape with an empty\ntoken would be lying to the caller.",
        "properties": {
          "customer_id": {
            "title": "Customer Id",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "object": {
            "const": "billing_portal.session",
            "default": "billing_portal.session",
            "title": "Object",
            "type": "string"
          },
          "revoked_at": {
            "title": "Revoked At",
            "type": "integer"
          },
          "subscription_id": {
            "title": "Subscription Id",
            "type": "string"
          }
        },
        "required": [
          "id",
          "livemode",
          "subscription_id",
          "customer_id",
          "revoked_at"
        ],
        "title": "BillingPortalSessionRevokeResponse",
        "type": "object"
      },
      "ChangePlanRequest": {
        "additionalProperties": false,
        "description": "Body of the plan-change + preview routes. ``plan_id`` is a BillKit\nplan slug \u2014 monthly (``free`` | ``indie`` | ``growth`` | ``scale``) or\nannual (``indie_year`` | ``growth_year`` | ``scale_year``).",
        "properties": {
          "plan_id": {
            "title": "Plan Id",
            "type": "string"
          }
        },
        "required": [
          "plan_id"
        ],
        "title": "ChangePlanRequest",
        "type": "object"
      },
      "CheckoutConfirmRequest": {
        "additionalProperties": false,
        "description": "Body for ``POST /v1/checkout/sessions/{id}/confirm`` \u2014 the iframe hop.\n\nAuthenticated by the ephemeral ``client_secret`` (not an API key).",
        "properties": {
          "card_token": {
            "anyOf": [
              {
                "maxLength": 512,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Card Token"
          },
          "country": {
            "anyOf": [
              {
                "maxLength": 2,
                "minLength": 2,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country"
          },
          "issuer": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Issuer"
          },
          "method": {
            "enum": [
              "creditcard",
              "directdebit",
              "ideal",
              "applepay"
            ],
            "title": "Method",
            "type": "string"
          }
        },
        "required": [
          "method"
        ],
        "title": "CheckoutConfirmRequest",
        "type": "object"
      },
      "CheckoutConfirmResponse": {
        "properties": {
          "object": {
            "const": "checkout_confirmation",
            "default": "checkout_confirmation",
            "title": "Object",
            "type": "string"
          },
          "payment_status": {
            "title": "Payment Status",
            "type": "string"
          },
          "redirect_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Redirect Url"
          },
          "session_id": {
            "title": "Session Id",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "session_id",
          "status",
          "payment_status",
          "redirect_url"
        ],
        "title": "CheckoutConfirmResponse",
        "type": "object"
      },
      "CheckoutCouponRequest": {
        "additionalProperties": false,
        "description": "Body for ``POST /v1/checkout/sessions/{id}/coupon`` \u2014 the buyer's code.\n\nAuthenticated by the ephemeral ``client_secret``, like the rest of the\nelement's surface: this is the *buyer's browser* talking, not the\ntenant's backend.",
        "properties": {
          "code": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Code"
          }
        },
        "title": "CheckoutCouponRequest",
        "type": "object"
      },
      "CheckoutElementResponse": {
        "description": "Bootstrap payload the js.billkit.eu iframe reads on mount.",
        "properties": {
          "allow_promotion_codes": {
            "default": false,
            "title": "Allow Promotion Codes",
            "type": "boolean"
          },
          "amount_due_now": {
            "title": "Amount Due Now",
            "type": "integer"
          },
          "cancel_url": {
            "title": "Cancel Url",
            "type": "string"
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country"
          },
          "country_suggestion": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country Suggestion"
          },
          "coupon_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Coupon Code"
          },
          "coupon_duration": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Coupon Duration"
          },
          "coupon_duration_in_months": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Coupon Duration In Months"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "discount_cents": {
            "default": 0,
            "title": "Discount Cents",
            "type": "integer"
          },
          "ideal_issuers": {
            "default": [],
            "items": {
              "$ref": "#/components/schemas/IdealIssuerResponse"
            },
            "title": "Ideal Issuers",
            "type": "array"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "merchant_logo_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Merchant Logo Url"
          },
          "merchant_name": {
            "title": "Merchant Name",
            "type": "string"
          },
          "methods": {
            "items": {
              "type": "string"
            },
            "title": "Methods",
            "type": "array"
          },
          "object": {
            "const": "checkout_element",
            "default": "checkout_element",
            "title": "Object",
            "type": "string"
          },
          "product_name": {
            "title": "Product Name",
            "type": "string"
          },
          "profile_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Profile Id"
          },
          "recurring_amount": {
            "title": "Recurring Amount",
            "type": "integer"
          },
          "recurring_amount_discounted": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Recurring Amount Discounted"
          },
          "recurring_interval": {
            "title": "Recurring Interval",
            "type": "string"
          },
          "requires_verification": {
            "title": "Requires Verification",
            "type": "boolean"
          },
          "session_id": {
            "title": "Session Id",
            "type": "string"
          },
          "show_header": {
            "default": true,
            "title": "Show Header",
            "type": "boolean"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "success_url": {
            "title": "Success Url",
            "type": "string"
          },
          "trial_days": {
            "title": "Trial Days",
            "type": "integer"
          }
        },
        "required": [
          "session_id",
          "status",
          "livemode",
          "currency",
          "amount_due_now",
          "recurring_amount",
          "recurring_interval",
          "trial_days",
          "requires_verification",
          "methods",
          "product_name",
          "merchant_name",
          "success_url",
          "cancel_url"
        ],
        "title": "CheckoutElementResponse",
        "type": "object"
      },
      "CheckoutPaymentMethodsResponse": {
        "description": "Response for ``GET /v1/checkout/payment-methods`` (Checkout-token auth).\n\nAlso the response shape of the Set default / Remove mutations, which\nreturn the refreshed wallet so the element reconciles its optimistic\nupdate against the server's truth.",
        "properties": {
          "customer_id": {
            "title": "Customer Id",
            "type": "string"
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/CheckoutSavedMethod"
            },
            "title": "Data",
            "type": "array"
          },
          "ideal_issuers": {
            "default": [],
            "items": {
              "$ref": "#/components/schemas/IdealIssuerResponse"
            },
            "title": "Ideal Issuers",
            "type": "array"
          },
          "livemode": {
            "default": false,
            "title": "Livemode",
            "type": "boolean"
          },
          "methods": {
            "default": [],
            "items": {
              "type": "string"
            },
            "title": "Methods",
            "type": "array"
          },
          "object": {
            "const": "checkout_payment_methods",
            "default": "checkout_payment_methods",
            "title": "Object",
            "type": "string"
          },
          "profile_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Profile Id"
          }
        },
        "required": [
          "customer_id",
          "data"
        ],
        "title": "CheckoutPaymentMethodsResponse",
        "type": "object"
      },
      "CheckoutSavedMethod": {
        "description": "One saved payment method for the ``<PaymentMethodElement/>`` wallet.\n\nDerived from the customer's live subscription mandates. Card fields are\n``null`` for non-card mandates (SEPA / iDEAL).",
        "properties": {
          "brand": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Brand"
          },
          "exp_month": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Exp Month"
          },
          "exp_year": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Exp Year"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "is_default": {
            "default": false,
            "title": "Is Default",
            "type": "boolean"
          },
          "kind": {
            "title": "Kind",
            "type": "string"
          },
          "last4": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last4"
          }
        },
        "required": [
          "id",
          "kind"
        ],
        "title": "CheckoutSavedMethod",
        "type": "object"
      },
      "CheckoutSessionCreate": {
        "additionalProperties": false,
        "properties": {
          "cancel_url": {
            "format": "uri",
            "maxLength": 2083,
            "minLength": 1,
            "title": "Cancel Url",
            "type": "string"
          },
          "country": {
            "anyOf": [
              {
                "maxLength": 2,
                "minLength": 2,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country"
          },
          "coupon_code": {
            "anyOf": [
              {
                "maxLength": 64,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Coupon Code"
          },
          "customer_email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Customer Email"
          },
          "customer_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Customer Id"
          },
          "customer_name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Customer Name"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "maxLength": 500,
                  "type": "string"
                },
                "maxProperties": 50,
                "propertyNames": {
                  "maxLength": 40
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "method": {
            "anyOf": [
              {
                "enum": [
                  "creditcard",
                  "directdebit",
                  "ideal",
                  "applepay"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Method"
          },
          "price_id": {
            "title": "Price Id",
            "type": "string"
          },
          "success_url": {
            "format": "uri",
            "maxLength": 2083,
            "minLength": 1,
            "title": "Success Url",
            "type": "string"
          },
          "trial_days_override": {
            "anyOf": [
              {
                "maximum": 180.0,
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial Days Override"
          },
          "ui_mode": {
            "default": "hosted",
            "enum": [
              "hosted",
              "embedded"
            ],
            "title": "Ui Mode",
            "type": "string"
          }
        },
        "required": [
          "price_id",
          "success_url",
          "cancel_url"
        ],
        "title": "CheckoutSessionCreate",
        "type": "object"
      },
      "CheckoutSessionResponse": {
        "properties": {
          "cancel_url": {
            "title": "Cancel Url",
            "type": "string"
          },
          "client_secret": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Client Secret"
          },
          "coupon_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Coupon Id"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "customer_country_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Customer Country Code"
          },
          "customer_email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Customer Email"
          },
          "customer_id": {
            "title": "Customer Id",
            "type": "string"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "metadata": {
            "additionalProperties": {
              "type": "string"
            },
            "default": {},
            "title": "Metadata",
            "type": "object"
          },
          "method": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Method"
          },
          "object": {
            "const": "checkout_session",
            "default": "checkout_session",
            "title": "Object",
            "type": "string"
          },
          "payment_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Payment Id"
          },
          "price_id": {
            "title": "Price Id",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "subscription_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Subscription Id"
          },
          "success_url": {
            "title": "Success Url",
            "type": "string"
          },
          "trial_days_override": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial Days Override"
          },
          "ui_mode": {
            "title": "Ui Mode",
            "type": "string"
          },
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "customer_id",
          "price_id",
          "success_url",
          "cancel_url",
          "status",
          "ui_mode",
          "url",
          "client_secret",
          "subscription_id",
          "payment_id",
          "expires_at",
          "trial_days_override",
          "coupon_id",
          "method"
        ],
        "title": "CheckoutSessionResponse",
        "type": "object"
      },
      "CheckoutSetupConfirmRequest": {
        "additionalProperties": false,
        "description": "Body for ``POST /v1/checkout/payment-methods/setup/confirm``.",
        "properties": {
          "card_token": {
            "anyOf": [
              {
                "maxLength": 512,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Card Token"
          },
          "client_secret": {
            "maxLength": 256,
            "title": "Client Secret",
            "type": "string"
          },
          "issuer": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Issuer"
          },
          "method": {
            "enum": [
              "creditcard",
              "directdebit",
              "ideal",
              "applepay"
            ],
            "title": "Method",
            "type": "string"
          }
        },
        "required": [
          "client_secret",
          "method"
        ],
        "title": "CheckoutSetupConfirmRequest",
        "type": "object"
      },
      "CheckoutSetupConfirmResponse": {
        "description": "Response for ``POST /v1/checkout/payment-methods/setup/confirm``.\n\n``redirect_url`` is Mollie's next-action URL (3DS / iDEAL bank) the\nelement hands to the SDK for the top-window redirect; NULL when the\nverification already reached a terminal status without one.",
        "properties": {
          "object": {
            "const": "checkout_setup_confirmation",
            "default": "checkout_setup_confirmation",
            "title": "Object",
            "type": "string"
          },
          "redirect_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Redirect Url"
          },
          "setup_id": {
            "title": "Setup Id",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "setup_id",
          "status",
          "redirect_url"
        ],
        "title": "CheckoutSetupConfirmResponse",
        "type": "object"
      },
      "CheckoutSetupResponse": {
        "description": "Response for ``POST /v1/checkout/payment-methods/setup``.\n\nStripe SetupIntent shape: ``client_secret`` is confirmed by the element\n(with a tokenised card / chosen bank) to mint a fresh mandate. The\namount is the tiny verification charge Mollie needs to create a card\nmandate \u2014 refunded/ignored by the tenant, never a real sale.",
        "properties": {
          "amount_due_now": {
            "title": "Amount Due Now",
            "type": "integer"
          },
          "client_secret": {
            "title": "Client Secret",
            "type": "string"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "object": {
            "const": "checkout_setup",
            "default": "checkout_setup",
            "title": "Object",
            "type": "string"
          },
          "setup_id": {
            "title": "Setup Id",
            "type": "string"
          }
        },
        "required": [
          "setup_id",
          "client_secret",
          "currency",
          "amount_due_now"
        ],
        "title": "CheckoutSetupResponse",
        "type": "object"
      },
      "CouponCreate": {
        "additionalProperties": false,
        "properties": {
          "applies_to_price_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Applies To Price Ids"
          },
          "code": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Code",
            "type": "string"
          },
          "discount_type": {
            "enum": [
              "percent",
              "fixed_cents"
            ],
            "title": "Discount Type",
            "type": "string"
          },
          "discount_value": {
            "minimum": 1.0,
            "title": "Discount Value",
            "type": "integer"
          },
          "duration": {
            "default": "once",
            "enum": [
              "once",
              "forever",
              "repeating"
            ],
            "title": "Duration",
            "type": "string"
          },
          "duration_in_months": {
            "anyOf": [
              {
                "maximum": 120.0,
                "minimum": 1.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration In Months"
          },
          "max_redemptions": {
            "anyOf": [
              {
                "minimum": 1.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Redemptions"
          },
          "min_amount_cents": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Min Amount Cents"
          },
          "redeem_by": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Redeem By"
          }
        },
        "required": [
          "code",
          "discount_type",
          "discount_value"
        ],
        "title": "CouponCreate",
        "type": "object"
      },
      "CouponResponse": {
        "properties": {
          "active": {
            "title": "Active",
            "type": "boolean"
          },
          "applies_to_price_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Applies To Price Ids"
          },
          "code": {
            "title": "Code",
            "type": "string"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "discount_type": {
            "title": "Discount Type",
            "type": "string"
          },
          "discount_value": {
            "title": "Discount Value",
            "type": "integer"
          },
          "duration": {
            "title": "Duration",
            "type": "string"
          },
          "duration_in_months": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration In Months"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "max_redemptions": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Redemptions"
          },
          "min_amount_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Min Amount Cents"
          },
          "object": {
            "const": "coupon",
            "default": "coupon",
            "title": "Object",
            "type": "string"
          },
          "redeem_by": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Redeem By"
          },
          "redemptions_count": {
            "title": "Redemptions Count",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "code",
          "discount_type",
          "discount_value",
          "duration",
          "duration_in_months",
          "max_redemptions",
          "redemptions_count",
          "redeem_by",
          "applies_to_price_ids",
          "min_amount_cents",
          "active"
        ],
        "title": "CouponResponse",
        "type": "object"
      },
      "CouponUpdate": {
        "additionalProperties": false,
        "properties": {
          "active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Active"
          },
          "applies_to_price_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Applies To Price Ids"
          },
          "max_redemptions": {
            "anyOf": [
              {
                "minimum": 1.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Redemptions"
          },
          "min_amount_cents": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Min Amount Cents"
          },
          "redeem_by": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Redeem By"
          }
        },
        "title": "CouponUpdate",
        "type": "object"
      },
      "CouponValidateRequest": {
        "additionalProperties": false,
        "properties": {
          "amount_cents": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Amount Cents"
          },
          "code": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Code",
            "type": "string"
          },
          "price_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Price Id"
          }
        },
        "required": [
          "code"
        ],
        "title": "CouponValidateRequest",
        "type": "object"
      },
      "CouponValidateResponse": {
        "properties": {
          "code": {
            "title": "Code",
            "type": "string"
          },
          "coupon_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Coupon Id"
          },
          "discount_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Discount Cents"
          },
          "discount_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Discount Type"
          },
          "discount_value": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Discount Value"
          },
          "duration": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration"
          },
          "final_charge_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Final Charge Cents"
          },
          "object": {
            "const": "coupon_validation",
            "default": "coupon_validation",
            "title": "Object",
            "type": "string"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "valid": {
            "title": "Valid",
            "type": "boolean"
          }
        },
        "required": [
          "valid",
          "coupon_id",
          "code",
          "discount_type",
          "discount_value",
          "duration",
          "discount_cents",
          "final_charge_cents",
          "reason"
        ],
        "title": "CouponValidateResponse",
        "type": "object"
      },
      "CreditNoteResponse": {
        "properties": {
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "customer_id": {
            "title": "Customer Id",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "invoice_id": {
            "title": "Invoice Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "number": {
            "title": "Number",
            "type": "string"
          },
          "object": {
            "const": "credit_note",
            "default": "credit_note",
            "title": "Object",
            "type": "string"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "refund_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Refund Id"
          },
          "subtotal_cents": {
            "title": "Subtotal Cents",
            "type": "integer"
          },
          "tax_cents": {
            "title": "Tax Cents",
            "type": "integer"
          },
          "tax_country_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tax Country Code"
          },
          "tax_rate_basis_points": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tax Rate Basis Points"
          },
          "tax_reverse_charged": {
            "title": "Tax Reverse Charged",
            "type": "boolean"
          },
          "total_cents": {
            "title": "Total Cents",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "invoice_id",
          "refund_id",
          "customer_id",
          "number",
          "currency",
          "subtotal_cents",
          "tax_cents",
          "total_cents",
          "tax_country_code",
          "tax_reverse_charged",
          "tax_rate_basis_points",
          "reason"
        ],
        "title": "CreditNoteResponse",
        "type": "object"
      },
      "CustomerCreate": {
        "additionalProperties": false,
        "properties": {
          "country_code": {
            "anyOf": [
              {
                "maxLength": 2,
                "minLength": 2,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country Code"
          },
          "email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "maxLength": 500,
                  "type": "string"
                },
                "maxProperties": 50,
                "propertyNames": {
                  "maxLength": 40
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "test_clock": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Test Clock"
          }
        },
        "title": "CustomerCreate",
        "type": "object"
      },
      "CustomerPurgeRequest": {
        "additionalProperties": false,
        "properties": {
          "confirmed": {
            "default": false,
            "description": "Must be true to actually purge. Guards against fat-finger calls that meant to soft-delete.",
            "title": "Confirmed",
            "type": "boolean"
          }
        },
        "title": "CustomerPurgeRequest",
        "type": "object"
      },
      "CustomerResponse": {
        "properties": {
          "country_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country Code"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "metadata": {
            "additionalProperties": {
              "type": "string"
            },
            "title": "Metadata",
            "type": "object"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "object": {
            "const": "customer",
            "default": "customer",
            "title": "Object",
            "type": "string"
          },
          "provisional": {
            "title": "Provisional",
            "type": "boolean"
          },
          "stats": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CustomerStatsInfo"
              },
              {
                "type": "null"
              }
            ]
          },
          "test_clock": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Test Clock"
          },
          "vat_number": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Vat Number"
          },
          "vat_number_validated": {
            "title": "Vat Number Validated",
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "email",
          "name",
          "metadata",
          "country_code",
          "vat_number",
          "vat_number_validated",
          "test_clock",
          "provisional"
        ],
        "title": "CustomerResponse",
        "type": "object"
      },
      "CustomerStatsInfo": {
        "description": "What a customer holds and what they have paid.\n\n``lifetime_cents`` is net cash: charges that settled minus refunds\nthat settled. Backward-looking, unlike the MRR figure it sits beside\non the console's customer list. See ``services/customer_stats.py``.",
        "properties": {
          "currency": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Currency"
          },
          "lifetime_cents": {
            "title": "Lifetime Cents",
            "type": "integer"
          },
          "object": {
            "const": "customer.stats",
            "default": "customer.stats",
            "title": "Object",
            "type": "string"
          },
          "subscription_count": {
            "title": "Subscription Count",
            "type": "integer"
          }
        },
        "required": [
          "subscription_count",
          "lifetime_cents",
          "currency"
        ],
        "title": "CustomerStatsInfo",
        "type": "object"
      },
      "CustomerUpdate": {
        "additionalProperties": false,
        "properties": {
          "country_code": {
            "anyOf": [
              {
                "maxLength": 2,
                "minLength": 2,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country Code"
          },
          "email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "maxLength": 500,
                  "type": "string"
                },
                "maxProperties": 50,
                "propertyNames": {
                  "maxLength": 40
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "title": "CustomerUpdate",
        "type": "object"
      },
      "CustomerVatNumberRequest": {
        "additionalProperties": false,
        "description": "``POST /v1/customers/{id}/vat_number`` body.\n\nThere is no ``mark_validated`` field: every non-empty submission\nis run through VIES server-side (see ``services/vies.py``). An\ninvalid number gets a ``400 parameter_invalid``; a VIES outage\npersists the number with ``vat_validation_state='unverifiable'``\nso the customer can retry later.",
        "properties": {
          "country_code": {
            "anyOf": [
              {
                "maxLength": 2,
                "minLength": 2,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country Code"
          },
          "vat_number": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Vat Number"
          }
        },
        "title": "CustomerVatNumberRequest",
        "type": "object"
      },
      "DeletedResource": {
        "description": "What a ``DELETE`` returns once the object is gone.\n\nReturning the full object would say the opposite of what happened: the\ncaller would get back a body that reads like a live resource, for\nsomething that no longer answers a ``GET``. This shape says the one\nthing that is true, and it is the only shape a ``DELETE`` in this API\nreturns.\n\n``DELETE`` is reserved for exactly that outcome. A resource that has to\nstay readable, which is any of them that decides what a customer was\ncharged, is retired through its update route instead with\n``active: false``, because it was never deleted. A price, a product, a\ntax rate and a coupon all work that way. Customers, webhook endpoints\nand test clocks really do leave, so they keep the verb.",
        "properties": {
          "deleted": {
            "const": true,
            "default": true,
            "title": "Deleted",
            "type": "boolean"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "id",
          "object"
        ],
        "title": "DeletedResource",
        "type": "object"
      },
      "DisputeResponse": {
        "properties": {
          "amount_cents": {
            "title": "Amount Cents",
            "type": "integer"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "object": {
            "const": "dispute",
            "default": "dispute",
            "title": "Object",
            "type": "string"
          },
          "one_shot_payment_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "One Shot Payment Id"
          },
          "payment_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Payment Id"
          },
          "provider_chargeback_id": {
            "title": "Provider Chargeback Id",
            "type": "string"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "reversed": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reversed"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "subscription_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Subscription Id"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "payment_id",
          "one_shot_payment_id",
          "subscription_id",
          "provider_chargeback_id",
          "amount_cents",
          "currency",
          "reason",
          "status",
          "reversed"
        ],
        "title": "DisputeResponse",
        "type": "object"
      },
      "DomainCreateRequest": {
        "additionalProperties": false,
        "properties": {
          "domain": {
            "title": "Domain",
            "type": "string"
          }
        },
        "required": [
          "domain"
        ],
        "title": "DomainCreateRequest",
        "type": "object"
      },
      "DomainRecordInfo": {
        "properties": {
          "found": {
            "title": "Found",
            "type": "boolean"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "required": {
            "title": "Required",
            "type": "boolean"
          },
          "type": {
            "enum": [
              "TXT",
              "CNAME"
            ],
            "title": "Type",
            "type": "string"
          },
          "value": {
            "title": "Value",
            "type": "string"
          }
        },
        "required": [
          "type",
          "name",
          "value",
          "found",
          "required"
        ],
        "title": "DomainRecordInfo",
        "type": "object"
      },
      "DomainResponse": {
        "properties": {
          "check_attempts": {
            "title": "Check Attempts",
            "type": "integer"
          },
          "cname_found": {
            "title": "Cname Found",
            "type": "boolean"
          },
          "domain": {
            "title": "Domain",
            "type": "string"
          },
          "fallback_portal": {
            "title": "Fallback Portal",
            "type": "string"
          },
          "fallback_sender": {
            "title": "Fallback Sender",
            "type": "string"
          },
          "last_checked_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Checked At"
          },
          "object": {
            "const": "onboarding.domain",
            "default": "onboarding.domain",
            "title": "Object",
            "type": "string"
          },
          "records": {
            "items": {
              "$ref": "#/components/schemas/DomainRecordInfo"
            },
            "title": "Records",
            "type": "array"
          },
          "status": {
            "enum": [
              "pending",
              "verified",
              "failed"
            ],
            "title": "Status",
            "type": "string"
          },
          "txt_found": {
            "title": "Txt Found",
            "type": "boolean"
          },
          "verified_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Verified At"
          }
        },
        "required": [
          "domain",
          "status",
          "txt_found",
          "cname_found",
          "check_attempts",
          "records",
          "fallback_portal",
          "fallback_sender",
          "last_checked_at",
          "verified_at"
        ],
        "title": "DomainResponse",
        "type": "object"
      },
      "EventResponse": {
        "properties": {
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "customer": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ExpandedCustomer"
              },
              {
                "type": "null"
              }
            ]
          },
          "data": {
            "additionalProperties": true,
            "title": "Data",
            "type": "object"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "object": {
            "const": "event",
            "default": "event",
            "title": "Object",
            "type": "string"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "type",
          "data"
        ],
        "title": "EventResponse",
        "type": "object"
      },
      "EventTypeListResponse": {
        "description": "The catalogue a tenant may subscribe to.\n\nDeliberately not the standard cursor-paginated ``ListResponse``: this is a\nsmall closed set that changes with a deployment, not a page of tenant\nrecords, and paginating it would imply otherwise.",
        "properties": {
          "data": {
            "items": {
              "type": "string"
            },
            "title": "Data",
            "type": "array"
          },
          "object": {
            "const": "event_type_list",
            "default": "event_type_list",
            "title": "Object",
            "type": "string"
          },
          "wildcard": {
            "title": "Wildcard",
            "type": "string"
          }
        },
        "required": [
          "data",
          "wildcard"
        ],
        "title": "EventTypeListResponse",
        "type": "object"
      },
      "ExpandedCustomer": {
        "description": "Enough of a customer to render a row: who they are and where.\n\n``country_code`` is here because a billing table without a\njurisdiction column hides the thing EU billing turns on.",
        "properties": {
          "country_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country Code"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "object": {
            "const": "customer.summary",
            "default": "customer.summary",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "country_code"
        ],
        "title": "ExpandedCustomer",
        "type": "object"
      },
      "ExpandedPrice": {
        "description": "Enough of a price to render \"Pro \u00b7 monthly \u00b7 \u20ac49.00\".\n\n``product_name`` rides along because the pair is what a plan *is* to\na reader, and resolving the product separately would be a second\nround-trip for half a label.",
        "properties": {
          "active": {
            "title": "Active",
            "type": "boolean"
          },
          "amount_cents": {
            "title": "Amount Cents",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "interval": {
            "title": "Interval",
            "type": "string"
          },
          "object": {
            "const": "price.summary",
            "default": "price.summary",
            "title": "Object",
            "type": "string"
          },
          "payment_methods": {
            "items": {
              "type": "string"
            },
            "title": "Payment Methods",
            "type": "array"
          },
          "product_id": {
            "title": "Product Id",
            "type": "string"
          },
          "product_name": {
            "title": "Product Name",
            "type": "string"
          },
          "trial_days": {
            "title": "Trial Days",
            "type": "integer"
          },
          "unit_amount_decimal": {
            "title": "Unit Amount Decimal",
            "type": "string"
          },
          "usage_type": {
            "title": "Usage Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "product_id",
          "product_name",
          "amount_cents",
          "unit_amount_decimal",
          "currency",
          "interval",
          "usage_type",
          "active",
          "trial_days",
          "payment_methods"
        ],
        "title": "ExpandedPrice",
        "type": "object"
      },
      "ExpandedSubscription": {
        "description": "Enough of a subscription to say what a payment was for.",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "const": "subscription.summary",
            "default": "subscription.summary",
            "title": "Object",
            "type": "string"
          },
          "price_id": {
            "title": "Price Id",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id",
          "status",
          "price_id"
        ],
        "title": "ExpandedSubscription",
        "type": "object"
      },
      "GoLiveRequirementInfo": {
        "properties": {
          "key": {
            "title": "Key",
            "type": "string"
          },
          "level": {
            "enum": [
              "pass",
              "block",
              "warn"
            ],
            "title": "Level",
            "type": "string"
          }
        },
        "required": [
          "key",
          "level"
        ],
        "title": "GoLiveRequirementInfo",
        "type": "object"
      },
      "GoLiveResponse": {
        "properties": {
          "blocking": {
            "title": "Blocking",
            "type": "integer"
          },
          "can_go_live": {
            "title": "Can Go Live",
            "type": "boolean"
          },
          "is_live": {
            "title": "Is Live",
            "type": "boolean"
          },
          "object": {
            "const": "onboarding.go_live",
            "default": "onboarding.go_live",
            "title": "Object",
            "type": "string"
          },
          "requirements": {
            "items": {
              "$ref": "#/components/schemas/GoLiveRequirementInfo"
            },
            "title": "Requirements",
            "type": "array"
          }
        },
        "required": [
          "requirements",
          "blocking",
          "is_live",
          "can_go_live"
        ],
        "title": "GoLiveResponse",
        "type": "object"
      },
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "title": "HTTPValidationError",
        "type": "object"
      },
      "HomeMetricsResponse": {
        "properties": {
          "active_subscriptions": {
            "$ref": "#/components/schemas/_MetricPoint"
          },
          "as_of": {
            "title": "As Of",
            "type": "integer"
          },
          "failed_payments_24h": {
            "$ref": "#/components/schemas/_MetricPoint"
          },
          "mode": {
            "title": "Mode",
            "type": "string"
          },
          "mrr": {
            "$ref": "#/components/schemas/_MetricPoint"
          },
          "object": {
            "default": "metrics.home",
            "title": "Object",
            "type": "string"
          },
          "today_revenue": {
            "$ref": "#/components/schemas/_MetricPoint"
          }
        },
        "required": [
          "mode",
          "as_of",
          "mrr",
          "active_subscriptions",
          "today_revenue",
          "failed_payments_24h"
        ],
        "title": "HomeMetricsResponse",
        "type": "object"
      },
      "IdealIssuerResponse": {
        "description": "One iDEAL bank the embedded picker renders.",
        "properties": {
          "id": {
            "title": "Id",
            "type": "string"
          },
          "image": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Image"
          },
          "name": {
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ],
        "title": "IdealIssuerResponse",
        "type": "object"
      },
      "InvoiceEmailResponse": {
        "description": "Acknowledgement for ``POST /v1/invoices/{id}/email``.\n\n``recipient`` is echoed because it is the invoice's captured address,\nwhich may differ from the customer's current one \u2014 an operator\nre-sending after a \"I never got it\" ticket needs to see where it\nactually went.\n\nDelivery itself is best-effort: a 200 means BillKit handed the\nmessage to its deliverer, not that a mailbox accepted it.",
        "properties": {
          "invoice_id": {
            "title": "Invoice Id",
            "type": "string"
          },
          "object": {
            "const": "invoice.email",
            "default": "invoice.email",
            "title": "Object",
            "type": "string"
          },
          "recipient": {
            "title": "Recipient",
            "type": "string"
          },
          "sent": {
            "default": true,
            "title": "Sent",
            "type": "boolean"
          }
        },
        "required": [
          "invoice_id",
          "recipient"
        ],
        "title": "InvoiceEmailResponse",
        "type": "object"
      },
      "InvoiceLineItemResponse": {
        "properties": {
          "amount_cents": {
            "title": "Amount Cents",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "description": {
            "title": "Description",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "const": "invoice_line_item",
            "default": "invoice_line_item",
            "title": "Object",
            "type": "string"
          },
          "period_end": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Period End"
          },
          "period_start": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Period Start"
          },
          "quantity": {
            "title": "Quantity",
            "type": "integer"
          },
          "tax_rate_basis_points": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tax Rate Basis Points"
          }
        },
        "required": [
          "id",
          "description",
          "amount_cents",
          "currency",
          "quantity",
          "tax_rate_basis_points",
          "period_start",
          "period_end"
        ],
        "title": "InvoiceLineItemResponse",
        "type": "object"
      },
      "InvoiceResponse": {
        "properties": {
          "billing_address_at_invoice_time": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Billing Address At Invoice Time"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "customer": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ExpandedCustomer"
              },
              {
                "type": "null"
              }
            ]
          },
          "customer_business_name_at_invoice_time": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Customer Business Name At Invoice Time"
          },
          "customer_email_at_invoice_time": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Customer Email At Invoice Time"
          },
          "customer_id": {
            "title": "Customer Id",
            "type": "string"
          },
          "customer_name_at_invoice_time": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Customer Name At Invoice Time"
          },
          "customer_vat_number_at_invoice_time": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Customer Vat Number At Invoice Time"
          },
          "discount_cents": {
            "title": "Discount Cents",
            "type": "integer"
          },
          "due_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Due At"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "lines": {
            "items": {
              "$ref": "#/components/schemas/InvoiceLineItemResponse"
            },
            "title": "Lines",
            "type": "array"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "number": {
            "title": "Number",
            "type": "string"
          },
          "object": {
            "const": "invoice",
            "default": "invoice",
            "title": "Object",
            "type": "string"
          },
          "one_shot_payment_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "One Shot Payment Id"
          },
          "paid_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paid At"
          },
          "payment_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Payment Id"
          },
          "pdf_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pdf Url"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "subscription_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Subscription Id"
          },
          "subtotal_cents": {
            "title": "Subtotal Cents",
            "type": "integer"
          },
          "tax_cents": {
            "title": "Tax Cents",
            "type": "integer"
          },
          "tax_country_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tax Country Code"
          },
          "tax_reverse_charged": {
            "title": "Tax Reverse Charged",
            "type": "boolean"
          },
          "total_cents": {
            "title": "Total Cents",
            "type": "integer"
          },
          "voided_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Voided At"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "customer_id",
          "subscription_id",
          "payment_id",
          "one_shot_payment_id",
          "number",
          "currency",
          "subtotal_cents",
          "discount_cents",
          "tax_cents",
          "total_cents",
          "tax_country_code",
          "tax_reverse_charged",
          "status",
          "due_at",
          "paid_at",
          "voided_at",
          "pdf_url",
          "customer_email_at_invoice_time",
          "customer_name_at_invoice_time",
          "customer_business_name_at_invoice_time",
          "customer_vat_number_at_invoice_time",
          "billing_address_at_invoice_time",
          "lines"
        ],
        "title": "InvoiceResponse",
        "type": "object"
      },
      "InvoiceVoid": {
        "additionalProperties": false,
        "description": "Body of ``POST /v1/invoices/{id}/void``. Every field optional, so the\nroute accepts an empty body \u2014 voiding takes no arguments, and requiring\n``{}`` would be ceremony.",
        "properties": {
          "reason": {
            "anyOf": [
              {
                "maxLength": 500,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          }
        },
        "title": "InvoiceVoid",
        "type": "object"
      },
      "ListResponse_ApiKeyResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/ApiKeyResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[ApiKeyResponse]",
        "type": "object"
      },
      "ListResponse_AuditLogResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/AuditLogResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[AuditLogResponse]",
        "type": "object"
      },
      "ListResponse_CouponResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/CouponResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[CouponResponse]",
        "type": "object"
      },
      "ListResponse_CreditNoteResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/CreditNoteResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[CreditNoteResponse]",
        "type": "object"
      },
      "ListResponse_CustomerResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/CustomerResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[CustomerResponse]",
        "type": "object"
      },
      "ListResponse_DisputeResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/DisputeResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[DisputeResponse]",
        "type": "object"
      },
      "ListResponse_EventResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/EventResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[EventResponse]",
        "type": "object"
      },
      "ListResponse_InvoiceResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/InvoiceResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[InvoiceResponse]",
        "type": "object"
      },
      "ListResponse_PaymentResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/PaymentResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[PaymentResponse]",
        "type": "object"
      },
      "ListResponse_PriceResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/PriceResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[PriceResponse]",
        "type": "object"
      },
      "ListResponse_ProductResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/ProductResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[ProductResponse]",
        "type": "object"
      },
      "ListResponse_RefundResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/RefundResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[RefundResponse]",
        "type": "object"
      },
      "ListResponse_SubscriptionResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/SubscriptionResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[SubscriptionResponse]",
        "type": "object"
      },
      "ListResponse_TaxRateResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/TaxRateResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[TaxRateResponse]",
        "type": "object"
      },
      "ListResponse_TestClockResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/TestClockResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[TestClockResponse]",
        "type": "object"
      },
      "ListResponse_UsageRecordResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/UsageRecordResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[UsageRecordResponse]",
        "type": "object"
      },
      "ListResponse_WebhookDeliveryResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/WebhookDeliveryResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[WebhookDeliveryResponse]",
        "type": "object"
      },
      "ListResponse_WebhookEndpointResponse_": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/WebhookEndpointResponse"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "default": false,
            "title": "Has More",
            "type": "boolean"
          },
          "object": {
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "ListResponse[WebhookEndpointResponse]",
        "type": "object"
      },
      "MetaInvoiceInfo": {
        "description": "One BillKit invoice to the tenant (meta-billing slice 2).\n\n``status`` is the meta-invoice vocabulary (``draft`` | ``open`` |\n``paid`` | ``void``); slice 2 only ever issues ``open`` \u2014 there is no\ncollection to back a ``paid``. ``pdf_available`` reflects whether the\ndeployment can render the PDF (``INVOICE_PDF_ENABLED``), so the\nconsole can disable the download affordance rather than surface a 501.\nAll timestamps are epoch seconds.",
        "properties": {
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "issued_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Issued At"
          },
          "number": {
            "title": "Number",
            "type": "string"
          },
          "pdf_available": {
            "title": "Pdf Available",
            "type": "boolean"
          },
          "period_end": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Period End"
          },
          "period_start": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Period Start"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "subtotal_cents": {
            "title": "Subtotal Cents",
            "type": "integer"
          },
          "tax_cents": {
            "title": "Tax Cents",
            "type": "integer"
          },
          "tax_reverse_charged": {
            "title": "Tax Reverse Charged",
            "type": "boolean"
          },
          "total_cents": {
            "title": "Total Cents",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "number",
          "status",
          "currency",
          "subtotal_cents",
          "tax_cents",
          "total_cents",
          "tax_reverse_charged",
          "period_start",
          "period_end",
          "issued_at",
          "pdf_available"
        ],
        "title": "MetaInvoiceInfo",
        "type": "object"
      },
      "MetaInvoiceListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/MetaInvoiceInfo"
            },
            "title": "Data",
            "type": "array"
          },
          "object": {
            "const": "list",
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "MetaInvoiceListResponse",
        "type": "object"
      },
      "MetaPlanChangePreview": {
        "description": "Payload of ``POST /v1/account/billing/change_plan/preview`` \u2014 the\nmoney-honest quote shown before the operator confirms a plan change.\n\nBillKit bills tenants in arrears, so a mid-period change bills nothing now:\n``current_period_total_cents`` is what the CURRENT period's invoice will\ntotal at its end if the change proceeds (the time-blended old+new rate);\n``next_period_amount_cents`` is the steady-state (target flat) price.\n``mode`` explains how it applies (``trial_repoint`` | ``reanchor`` |\n``blend`` | ``switch_interval`` | ``blocked``); a ``switch_interval`` change\n(monthly \u2194 annual) re-anchors a fresh period on the new cadence, so\n``current_period_end`` is the NEW period's end and ``current_period_total_cents``\nis the carried old-plan arrears plus the new flat rate. ``blocked_reason``\n(``past_due`` | ``canceled`` | ``period_due``) and ``requires_authorization``\n(a paid target with no captured mandate) tell the console why to\ndisable/redirect confirm. All amounts are minor units; ``current_period_end``\nis epoch seconds.",
        "properties": {
          "amount_cents": {
            "title": "Amount Cents",
            "type": "integer"
          },
          "blocked_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Blocked Reason"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "current_period_end": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Period End"
          },
          "current_period_total_cents": {
            "title": "Current Period Total Cents",
            "type": "integer"
          },
          "from_plan_id": {
            "title": "From Plan Id",
            "type": "string"
          },
          "interval": {
            "title": "Interval",
            "type": "string"
          },
          "mode": {
            "title": "Mode",
            "type": "string"
          },
          "next_period_amount_cents": {
            "title": "Next Period Amount Cents",
            "type": "integer"
          },
          "object": {
            "const": "account.plan_change_preview",
            "default": "account.plan_change_preview",
            "title": "Object",
            "type": "string"
          },
          "requires_authorization": {
            "title": "Requires Authorization",
            "type": "boolean"
          },
          "to_plan_id": {
            "title": "To Plan Id",
            "type": "string"
          },
          "to_plan_name": {
            "title": "To Plan Name",
            "type": "string"
          }
        },
        "required": [
          "from_plan_id",
          "to_plan_id",
          "to_plan_name",
          "amount_cents",
          "currency",
          "interval",
          "mode",
          "blocked_reason",
          "requires_authorization",
          "current_period_total_cents",
          "current_period_end",
          "next_period_amount_cents"
        ],
        "title": "MetaPlanChangePreview",
        "type": "object"
      },
      "MetaPlanInfo": {
        "properties": {
          "amount_cents": {
            "title": "Amount Cents",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "features": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Features"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "interval": {
            "title": "Interval",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "amount_cents",
          "currency",
          "interval",
          "features"
        ],
        "title": "MetaPlanInfo",
        "type": "object"
      },
      "MetaPlanListResponse": {
        "description": "Payload of ``GET /v1/account/billing/plans`` \u2014 the active BillKit\nplans the operator can switch to (the plan-picker menu).",
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/MetaPlanInfo"
            },
            "title": "Data",
            "type": "array"
          },
          "object": {
            "const": "list",
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "MetaPlanListResponse",
        "type": "object"
      },
      "MetaSubscriptionInfo": {
        "properties": {
          "cancel_at_period_end": {
            "title": "Cancel At Period End",
            "type": "boolean"
          },
          "current_period_end": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Period End"
          },
          "current_period_start": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Period Start"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "trial_end": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial End"
          }
        },
        "required": [
          "id",
          "status",
          "current_period_start",
          "current_period_end",
          "trial_end",
          "cancel_at_period_end"
        ],
        "title": "MetaSubscriptionInfo",
        "type": "object"
      },
      "MfaChallengeResult": {
        "description": "A first factor accepted, a second still owed.",
        "properties": {
          "challenge_token": {
            "title": "Challenge Token",
            "type": "string"
          },
          "methods": {
            "items": {
              "type": "string"
            },
            "title": "Methods",
            "type": "array"
          },
          "object": {
            "const": "operator.mfa_challenge",
            "default": "operator.mfa_challenge",
            "title": "Object",
            "type": "string"
          },
          "status": {
            "const": "mfa_required",
            "default": "mfa_required",
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "challenge_token",
          "methods"
        ],
        "title": "MfaChallengeResult",
        "type": "object"
      },
      "NextInvoiceInfo": {
        "properties": {
          "amount_cents": {
            "title": "Amount Cents",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "period_end": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Period End"
          }
        },
        "required": [
          "amount_cents",
          "currency",
          "period_end"
        ],
        "title": "NextInvoiceInfo",
        "type": "object"
      },
      "OneShotPaymentCreate": {
        "additionalProperties": false,
        "description": "Body for ``POST /v1/checkout/one_shot``.\n\nA single ``sequenceType=oneoff`` charge \u2014 no subscription, no mandate.\n``method`` is required (validated against the tenant's Mollie capability\nallowlist for ``currency``, not a per-price one) so the caller commits\nto a concrete method up front.",
        "properties": {
          "amount_cents": {
            "exclusiveMinimum": 0.0,
            "title": "Amount Cents",
            "type": "integer"
          },
          "cancel_url": {
            "anyOf": [
              {
                "format": "uri",
                "maxLength": 2083,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cancel Url"
          },
          "currency": {
            "maxLength": 3,
            "minLength": 3,
            "title": "Currency",
            "type": "string"
          },
          "customer_id": {
            "maxLength": 64,
            "title": "Customer Id",
            "type": "string"
          },
          "description": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "maxLength": 500,
                  "type": "string"
                },
                "maxProperties": 50,
                "propertyNames": {
                  "maxLength": 40
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "method": {
            "enum": [
              "creditcard",
              "directdebit",
              "ideal",
              "bancontact",
              "eps",
              "applepay"
            ],
            "title": "Method",
            "type": "string"
          },
          "refund_window_days": {
            "anyOf": [
              {
                "maximum": 365.0,
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Refund Window Days"
          },
          "success_url": {
            "format": "uri",
            "maxLength": 2083,
            "minLength": 1,
            "title": "Success Url",
            "type": "string"
          },
          "tax_behavior": {
            "anyOf": [
              {
                "enum": [
                  "inclusive",
                  "exclusive"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tax Behavior"
          }
        },
        "required": [
          "customer_id",
          "amount_cents",
          "currency",
          "method",
          "success_url"
        ],
        "title": "OneShotPaymentCreate",
        "type": "object"
      },
      "OneShotPaymentResponse": {
        "properties": {
          "amount_cents": {
            "title": "Amount Cents",
            "type": "integer"
          },
          "amount_disputed_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Amount Disputed Cents"
          },
          "amount_refundable_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Amount Refundable Cents"
          },
          "amount_refunded_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Amount Refunded Cents"
          },
          "cancel_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cancel Url"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "customer_id": {
            "title": "Customer Id",
            "type": "string"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At"
          },
          "failure_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Failure Reason"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "method": {
            "title": "Method",
            "type": "string"
          },
          "net_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Net Cents"
          },
          "object": {
            "const": "one_shot_payment",
            "default": "one_shot_payment",
            "title": "Object",
            "type": "string"
          },
          "paid_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paid At"
          },
          "redirect_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Redirect Url"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "success_url": {
            "title": "Success Url",
            "type": "string"
          },
          "tax_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tax Cents"
          },
          "tax_reverse_charged": {
            "default": false,
            "title": "Tax Reverse Charged",
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "customer_id",
          "amount_cents",
          "currency",
          "status",
          "method",
          "success_url",
          "cancel_url",
          "redirect_url",
          "expires_at",
          "paid_at",
          "failure_reason",
          "metadata"
        ],
        "title": "OneShotPaymentResponse",
        "type": "object"
      },
      "OperatorInfo": {
        "description": "Identity the console renders its shell from.",
        "properties": {
          "email": {
            "title": "Email",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "role": {
            "title": "Role",
            "type": "string"
          },
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          },
          "tenant_logo_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tenant Logo Url"
          },
          "tenant_name": {
            "title": "Tenant Name",
            "type": "string"
          }
        },
        "required": [
          "id",
          "email",
          "name",
          "tenant_id",
          "tenant_name",
          "role"
        ],
        "title": "OperatorInfo",
        "type": "object"
      },
      "PaymentResponse": {
        "properties": {
          "amount_cents": {
            "title": "Amount Cents",
            "type": "integer"
          },
          "amount_disputed_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Amount Disputed Cents"
          },
          "amount_refundable_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Amount Refundable Cents"
          },
          "amount_refunded_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Amount Refunded Cents"
          },
          "checkout_session_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Checkout Session Id"
          },
          "coupon_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Coupon Id"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "customer": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ExpandedCustomer"
              },
              {
                "type": "null"
              }
            ]
          },
          "customer_id": {
            "title": "Customer Id",
            "type": "string"
          },
          "discount_cents": {
            "default": 0,
            "title": "Discount Cents",
            "type": "integer"
          },
          "failure_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Failure Reason"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "object": {
            "const": "payment",
            "default": "payment",
            "title": "Object",
            "type": "string"
          },
          "paid_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Paid At"
          },
          "payment_method": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Payment Method"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "subscription": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ExpandedSubscription"
              },
              {
                "type": "null"
              }
            ]
          },
          "subscription_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Subscription Id"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "subscription_id",
          "customer_id",
          "checkout_session_id",
          "amount_cents",
          "currency",
          "status",
          "type",
          "paid_at",
          "failure_reason"
        ],
        "title": "PaymentResponse",
        "type": "object"
      },
      "PlanChangePreviewRequest": {
        "additionalProperties": false,
        "properties": {
          "target_price_id": {
            "title": "Target Price Id",
            "type": "string"
          }
        },
        "required": [
          "target_price_id"
        ],
        "title": "PlanChangePreviewRequest",
        "type": "object"
      },
      "PlanChangePreviewResponse": {
        "properties": {
          "charge_cents": {
            "title": "Charge Cents",
            "type": "integer"
          },
          "charge_net_cents": {
            "title": "Charge Net Cents",
            "type": "integer"
          },
          "charge_tax_cents": {
            "title": "Charge Tax Cents",
            "type": "integer"
          },
          "credit_cents": {
            "title": "Credit Cents",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "new_period_end": {
            "title": "New Period End",
            "type": "integer"
          },
          "proration_at": {
            "title": "Proration At",
            "type": "integer"
          },
          "refusal_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Refusal Reason"
          },
          "refused": {
            "title": "Refused",
            "type": "boolean"
          },
          "target_price_cents": {
            "title": "Target Price Cents",
            "type": "integer"
          },
          "target_price_id": {
            "title": "Target Price Id",
            "type": "string"
          }
        },
        "required": [
          "target_price_id",
          "target_price_cents",
          "currency",
          "credit_cents",
          "charge_cents",
          "charge_net_cents",
          "charge_tax_cents",
          "refused",
          "refusal_reason",
          "proration_at",
          "new_period_end"
        ],
        "title": "PlanChangePreviewResponse",
        "type": "object"
      },
      "PlanChangeUpdateRequest": {
        "additionalProperties": false,
        "properties": {
          "target_price_id": {
            "title": "Target Price Id",
            "type": "string"
          }
        },
        "required": [
          "target_price_id"
        ],
        "title": "PlanChangeUpdateRequest",
        "type": "object"
      },
      "PlatformAuthorizeResponse": {
        "description": "Payload of ``POST /v1/account/billing/authorize``.\n\n``checkout_url`` is Mollie's hosted page for the verification payment\nthat mints the platform mandate \u2014 the console redirects the operator\nthere; the mandate is captured by the platform webhook on completion.",
        "properties": {
          "checkout_url": {
            "title": "Checkout Url",
            "type": "string"
          },
          "object": {
            "const": "account.billing_authorize",
            "default": "account.billing_authorize",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "checkout_url"
        ],
        "title": "PlatformAuthorizeResponse",
        "type": "object"
      },
      "PortalApplyCouponBody": {
        "additionalProperties": false,
        "properties": {
          "code": {
            "title": "Code",
            "type": "string"
          }
        },
        "required": [
          "code"
        ],
        "title": "PortalApplyCouponBody",
        "type": "object"
      },
      "PortalApplyCouponResponse": {
        "description": "Apply-coupon response.\n\nReturns the structured discount (cents + currency) so the portal\nformats it with the shared ``formatCurrency`` helper, the same\nway every other amount is rendered. No pre-formatted string\ncrosses the wire \u2014 the API doesn't know the customer's locale.",
        "properties": {
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "discount_cents": {
            "title": "Discount Cents",
            "type": "integer"
          },
          "subscription": {
            "$ref": "#/components/schemas/PortalSubscriptionResponse"
          }
        },
        "required": [
          "subscription",
          "discount_cents",
          "currency"
        ],
        "title": "PortalApplyCouponResponse",
        "type": "object"
      },
      "PortalCreditNotePage": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/PortalCreditNoteRow"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          }
        },
        "required": [
          "data",
          "has_more"
        ],
        "title": "PortalCreditNotePage",
        "type": "object"
      },
      "PortalCreditNoteRow": {
        "description": "One credit note as the customer's portal shows it.\n\nShaped like :class:`PortalInvoiceRow` rather than mirroring\n``CreditNoteResponse``, because the portal renders the two in the same\nledger and a second shape would mean a second renderer. ``amount`` is the\npositive magnitude the row credits; the minus sign is the portal's, the\nsame way the PDF renders it \u2014 the stored figures are unsigned so the\n``total = subtotal + tax`` CHECK stays expressible.",
        "properties": {
          "amount": {
            "title": "Amount",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "date": {
            "title": "Date",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "invoice_id": {
            "title": "Invoice Id",
            "type": "string"
          },
          "number": {
            "title": "Number",
            "type": "string"
          },
          "pdf_available": {
            "title": "Pdf Available",
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "date",
          "amount",
          "currency",
          "number",
          "invoice_id",
          "pdf_available"
        ],
        "title": "PortalCreditNoteRow",
        "type": "object"
      },
      "PortalCustomer": {
        "properties": {
          "business_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Business Name"
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country"
          },
          "email": {
            "title": "Email",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "reverse_charge": {
            "default": false,
            "title": "Reverse Charge",
            "type": "boolean"
          },
          "tax_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tax Id"
          },
          "tax_id_validated": {
            "default": false,
            "title": "Tax Id Validated",
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "email"
        ],
        "title": "PortalCustomer",
        "type": "object"
      },
      "PortalCustomerUpdate": {
        "additionalProperties": false,
        "description": "``POST /v1/portal/customer`` body \u2014 the portal billing-details form.\n\n``tax_id`` is bounded here because ``customer.vat_number`` is\n``String(64)``: without the limit an over-long value reached the\ndriver and came back as a 500 on a form a *customer* is filling in.\nIts shape is checked one layer down, in\n:func:`services.customers.set_customer_vat_number`, so this route and\n``POST /v1/customers/{id}/vat_number`` cannot drift apart about what a\nVAT id is. An empty string still means \"clear it\", which is why the\nvalue is not normalised here.",
        "properties": {
          "business_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Business Name"
          },
          "country": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "tax_id": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tax Id"
          }
        },
        "title": "PortalCustomerUpdate",
        "type": "object"
      },
      "PortalInvoicePage": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/PortalInvoiceRow"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          }
        },
        "required": [
          "data",
          "has_more"
        ],
        "title": "PortalInvoicePage",
        "type": "object"
      },
      "PortalInvoiceRow": {
        "properties": {
          "amount": {
            "title": "Amount",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "date": {
            "title": "Date",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "pdf_available": {
            "title": "Pdf Available",
            "type": "boolean"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id",
          "date",
          "amount",
          "currency",
          "status",
          "pdf_available"
        ],
        "title": "PortalInvoiceRow",
        "type": "object"
      },
      "PortalLastFailedAttempt": {
        "properties": {
          "attempt": {
            "title": "Attempt",
            "type": "integer"
          },
          "human_reason": {
            "title": "Human Reason",
            "type": "string"
          },
          "max_attempts": {
            "title": "Max Attempts",
            "type": "integer"
          },
          "next_retry_at": {
            "title": "Next Retry At",
            "type": "string"
          },
          "reason_code": {
            "title": "Reason Code",
            "type": "string"
          }
        },
        "required": [
          "reason_code",
          "human_reason",
          "next_retry_at",
          "attempt",
          "max_attempts"
        ],
        "title": "PortalLastFailedAttempt",
        "type": "object"
      },
      "PortalPaymentAttempt": {
        "properties": {
          "amount": {
            "title": "Amount",
            "type": "integer"
          },
          "amount_refunded_cents": {
            "default": 0,
            "title": "Amount Refunded Cents",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "date": {
            "title": "Date",
            "type": "string"
          },
          "failure_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Failure Reason"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "method_label": {
            "title": "Method Label",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id",
          "date",
          "amount",
          "currency",
          "method_label",
          "status"
        ],
        "title": "PortalPaymentAttempt",
        "type": "object"
      },
      "PortalPaymentMethod": {
        "properties": {
          "brand": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Brand"
          },
          "exp_month": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Exp Month"
          },
          "exp_year": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Exp Year"
          },
          "fingerprint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Fingerprint"
          },
          "kind": {
            "title": "Kind",
            "type": "string"
          },
          "last4": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last4"
          }
        },
        "required": [
          "kind"
        ],
        "title": "PortalPaymentMethod",
        "type": "object"
      },
      "PortalPaymentsResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/PortalPaymentAttempt"
            },
            "title": "Data",
            "type": "array"
          }
        },
        "required": [
          "data"
        ],
        "title": "PortalPaymentsResponse",
        "type": "object"
      },
      "PortalPlanChangeBody": {
        "additionalProperties": false,
        "properties": {
          "cancel_at_period_end": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cancel At Period End"
          },
          "price_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Price Id"
          }
        },
        "title": "PortalPlanChangeBody",
        "type": "object"
      },
      "PortalPlanRow": {
        "properties": {
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "features": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Features"
          },
          "monthly": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PortalPlanSidePrice"
              },
              {
                "type": "null"
              }
            ]
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "product_id": {
            "title": "Product Id",
            "type": "string"
          },
          "yearly": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PortalPlanSidePrice"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "product_id",
          "name",
          "currency"
        ],
        "title": "PortalPlanRow",
        "type": "object"
      },
      "PortalPlanSidePrice": {
        "properties": {
          "price_id": {
            "title": "Price Id",
            "type": "string"
          },
          "unit_amount": {
            "title": "Unit Amount",
            "type": "integer"
          }
        },
        "required": [
          "price_id",
          "unit_amount"
        ],
        "title": "PortalPlanSidePrice",
        "type": "object"
      },
      "PortalPlansResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/PortalPlanRow"
            },
            "title": "Data",
            "type": "array"
          }
        },
        "required": [
          "data"
        ],
        "title": "PortalPlansResponse",
        "type": "object"
      },
      "PortalPreviewBody": {
        "additionalProperties": false,
        "properties": {
          "price_id": {
            "title": "Price Id",
            "type": "string"
          }
        },
        "required": [
          "price_id"
        ],
        "title": "PortalPreviewBody",
        "type": "object"
      },
      "PortalPrice": {
        "properties": {
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "interval": {
            "enum": [
              "month",
              "year"
            ],
            "title": "Interval",
            "type": "string"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "product_id": {
            "title": "Product Id",
            "type": "string"
          },
          "unit_amount": {
            "title": "Unit Amount",
            "type": "integer"
          },
          "unit_amount_decimal": {
            "default": "0",
            "title": "Unit Amount Decimal",
            "type": "string"
          },
          "usage_type": {
            "default": "licensed",
            "enum": [
              "licensed",
              "metered"
            ],
            "title": "Usage Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "product_id",
          "unit_amount",
          "currency",
          "interval"
        ],
        "title": "PortalPrice",
        "type": "object"
      },
      "PortalProduct": {
        "properties": {
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "marketing_features": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Marketing Features"
          },
          "name": {
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ],
        "title": "PortalProduct",
        "type": "object"
      },
      "PortalProrationPreview": {
        "properties": {
          "amount_due_today": {
            "title": "Amount Due Today",
            "type": "integer"
          },
          "credit_applied": {
            "title": "Credit Applied",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "description": {
            "title": "Description",
            "type": "string"
          },
          "next_renewal_amount": {
            "title": "Next Renewal Amount",
            "type": "integer"
          },
          "next_renewal_date": {
            "title": "Next Renewal Date",
            "type": "string"
          }
        },
        "required": [
          "amount_due_today",
          "currency",
          "next_renewal_amount",
          "next_renewal_date",
          "credit_applied",
          "description"
        ],
        "title": "PortalProrationPreview",
        "type": "object"
      },
      "PortalReauthorizeBody": {
        "additionalProperties": false,
        "properties": {
          "return_url": {
            "format": "uri",
            "maxLength": 2083,
            "minLength": 1,
            "title": "Return Url",
            "type": "string"
          }
        },
        "required": [
          "return_url"
        ],
        "title": "PortalReauthorizeBody",
        "type": "object"
      },
      "PortalRedirectResponse": {
        "properties": {
          "checkout_url": {
            "title": "Checkout Url",
            "type": "string"
          }
        },
        "required": [
          "checkout_url"
        ],
        "title": "PortalRedirectResponse",
        "type": "object"
      },
      "PortalSubscriptionResponse": {
        "properties": {
          "cancel_at_period_end": {
            "title": "Cancel At Period End",
            "type": "boolean"
          },
          "created_at": {
            "title": "Created At",
            "type": "string"
          },
          "current_period_end": {
            "title": "Current Period End",
            "type": "string"
          },
          "current_period_start": {
            "title": "Current Period Start",
            "type": "string"
          },
          "customer": {
            "$ref": "#/components/schemas/PortalCustomer"
          },
          "ended_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ended At"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "last_failed_attempt": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PortalLastFailedAttempt"
              },
              {
                "type": "null"
              }
            ]
          },
          "mandate_health": {
            "title": "Mandate Health",
            "type": "string"
          },
          "payment_method": {
            "$ref": "#/components/schemas/PortalPaymentMethod"
          },
          "pending_import_activation": {
            "default": false,
            "title": "Pending Import Activation",
            "type": "boolean"
          },
          "price": {
            "$ref": "#/components/schemas/PortalPrice"
          },
          "product": {
            "$ref": "#/components/schemas/PortalProduct"
          },
          "renewal_state": {
            "title": "Renewal State",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "tenant": {
            "$ref": "#/components/schemas/PortalTenantBranding"
          },
          "trial_end": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial End"
          }
        },
        "required": [
          "id",
          "status",
          "renewal_state",
          "cancel_at_period_end",
          "current_period_start",
          "current_period_end",
          "created_at",
          "mandate_health",
          "price",
          "product",
          "payment_method",
          "customer",
          "tenant"
        ],
        "title": "PortalSubscriptionResponse",
        "type": "object"
      },
      "PortalTenantBranding": {
        "properties": {
          "business_name": {
            "title": "Business Name",
            "type": "string"
          },
          "capabilities": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PortalTenantCapabilities"
              },
              {
                "type": "null"
              }
            ]
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Logo Url"
          },
          "support_email": {
            "title": "Support Email",
            "type": "string"
          },
          "theme": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PortalTenantTheme"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "business_name",
          "support_email"
        ],
        "title": "PortalTenantBranding",
        "type": "object"
      },
      "PortalTenantCapabilities": {
        "properties": {
          "checkout_header": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Checkout Header"
          },
          "coupons": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Coupons"
          },
          "cycle_enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cycle Enabled"
          },
          "invoice_pdf": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Invoice Pdf"
          },
          "powered_by": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Powered By"
          },
          "show_features": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Show Features"
          }
        },
        "title": "PortalTenantCapabilities",
        "type": "object"
      },
      "PortalTenantTheme": {
        "additionalProperties": true,
        "properties": {
          "display": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display"
          },
          "font": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Font"
          },
          "on_primary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "On Primary"
          },
          "palette": {
            "anyOf": [
              {
                "enum": [
                  "studio",
                  "blank"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Palette"
          },
          "powered_by": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Powered By"
          },
          "primary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Primary"
          },
          "primary_100": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Primary 100"
          },
          "primary_50": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Primary 50"
          },
          "primary_600": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Primary 600"
          },
          "radius": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Radius"
          },
          "stub_a": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Stub A"
          },
          "stub_b": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Stub B"
          }
        },
        "title": "PortalTenantTheme",
        "type": "object"
      },
      "PriceCreate": {
        "additionalProperties": false,
        "properties": {
          "amount_cents": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Amount Cents"
          },
          "billing_scheme": {
            "default": "per_unit",
            "enum": [
              "per_unit",
              "tiered"
            ],
            "title": "Billing Scheme",
            "type": "string"
          },
          "currency": {
            "default": "EUR",
            "maxLength": 3,
            "minLength": 3,
            "title": "Currency",
            "type": "string"
          },
          "interval": {
            "enum": [
              "month",
              "year"
            ],
            "title": "Interval",
            "type": "string"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "maxLength": 500,
                  "type": "string"
                },
                "maxProperties": 50,
                "propertyNames": {
                  "maxLength": 40
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "payment_methods": {
            "default": [
              "creditcard"
            ],
            "items": {
              "enum": [
                "creditcard",
                "directdebit",
                "ideal",
                "applepay"
              ],
              "type": "string"
            },
            "minItems": 1,
            "title": "Payment Methods",
            "type": "array"
          },
          "product_id": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Product Id",
            "type": "string"
          },
          "refund_on_cancel": {
            "default": "none",
            "description": "What a cancellation refunds, against the most recent charge. 'none' (default) refunds nothing. 'full' refunds the whole charge and ends access immediately. 'prorated' refunds the unused part of the current period and also ends access. Both are still bounded by the refund window below. Metered prices must leave this at 'none': ending access mid-period would strand usage that has not been billed yet.",
            "enum": [
              "none",
              "full",
              "prorated"
            ],
            "title": "Refund On Cancel",
            "type": "string"
          },
          "refund_window_initial_days": {
            "anyOf": [
              {
                "maximum": 365.0,
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Refund Window Initial Days"
          },
          "refund_window_renewal_days": {
            "anyOf": [
              {
                "maximum": 365.0,
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Refund Window Renewal Days"
          },
          "tax_behavior": {
            "default": "unspecified",
            "enum": [
              "inclusive",
              "exclusive",
              "unspecified"
            ],
            "title": "Tax Behavior",
            "type": "string"
          },
          "tiers": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/PriceTierInput"
                },
                "maxItems": 50,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tiers"
          },
          "tiers_mode": {
            "anyOf": [
              {
                "enum": [
                  "graduated",
                  "volume"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tiers Mode"
          },
          "trial_days": {
            "default": 0,
            "maximum": 90.0,
            "minimum": 0.0,
            "title": "Trial Days",
            "type": "integer"
          },
          "trial_verification_cents": {
            "default": 100,
            "minimum": 0.0,
            "title": "Trial Verification Cents",
            "type": "integer"
          },
          "unit_amount_decimal": {
            "anyOf": [
              {
                "maxLength": 32,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Per-unit rate in minor units with up to 12 decimal places, as a string ('0.02' means 0.02 cents). Metered prices only, and mutually exclusive with amount_cents. Always a string: a JSON number cannot hold this value exactly.",
            "title": "Unit Amount Decimal"
          },
          "usage_type": {
            "default": "licensed",
            "enum": [
              "licensed",
              "metered"
            ],
            "title": "Usage Type",
            "type": "string"
          }
        },
        "required": [
          "product_id",
          "interval"
        ],
        "title": "PriceCreate",
        "type": "object"
      },
      "PriceResponse": {
        "properties": {
          "active": {
            "title": "Active",
            "type": "boolean"
          },
          "amount_cents": {
            "title": "Amount Cents",
            "type": "integer"
          },
          "billing_scheme": {
            "title": "Billing Scheme",
            "type": "string"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "interval": {
            "title": "Interval",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "metadata": {
            "additionalProperties": {
              "type": "string"
            },
            "title": "Metadata",
            "type": "object"
          },
          "object": {
            "const": "price",
            "default": "price",
            "title": "Object",
            "type": "string"
          },
          "payment_methods": {
            "items": {
              "type": "string"
            },
            "title": "Payment Methods",
            "type": "array"
          },
          "product_id": {
            "title": "Product Id",
            "type": "string"
          },
          "product_name": {
            "title": "Product Name",
            "type": "string"
          },
          "refund_on_cancel": {
            "enum": [
              "none",
              "full",
              "prorated"
            ],
            "title": "Refund On Cancel",
            "type": "string"
          },
          "refund_window_initial_days": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Refund Window Initial Days"
          },
          "refund_window_renewal_days": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Refund Window Renewal Days"
          },
          "tax_behavior": {
            "title": "Tax Behavior",
            "type": "string"
          },
          "tiers": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/PriceTier"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tiers"
          },
          "tiers_mode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tiers Mode"
          },
          "trial_days": {
            "title": "Trial Days",
            "type": "integer"
          },
          "trial_verification_cents": {
            "title": "Trial Verification Cents",
            "type": "integer"
          },
          "unit_amount_decimal": {
            "title": "Unit Amount Decimal",
            "type": "string"
          },
          "usage_type": {
            "title": "Usage Type",
            "type": "string"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "product_id",
          "product_name",
          "amount_cents",
          "unit_amount_decimal",
          "currency",
          "interval",
          "active",
          "metadata",
          "trial_days",
          "trial_verification_cents",
          "payment_methods",
          "refund_on_cancel",
          "refund_window_initial_days",
          "refund_window_renewal_days",
          "tax_behavior",
          "usage_type",
          "billing_scheme",
          "tiers_mode",
          "tiers"
        ],
        "title": "PriceResponse",
        "type": "object"
      },
      "PriceTier": {
        "description": "A band as stored and read back. ``up_to: null`` is open-ended.",
        "properties": {
          "flat_amount": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Flat Amount"
          },
          "unit_amount_decimal": {
            "title": "Unit Amount Decimal",
            "type": "string"
          },
          "up_to": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Up To"
          }
        },
        "required": [
          "up_to",
          "unit_amount_decimal",
          "flat_amount"
        ],
        "title": "PriceTier",
        "type": "object"
      },
      "PriceTierInput": {
        "additionalProperties": false,
        "description": "One band of a tiered price.\n\n``up_to`` is inclusive, and the last band must be open-ended \u2014\n``\"inf\"``, Stripe's spelling \u2014 because a bounded top band cannot price\nthe usage above it. Bands must strictly increase.\n\nA band names a unit rate (``unit_amount`` in whole minor units, or\n``unit_amount_decimal`` as a string for finer rates), a ``flat_amount``\ncharged once for reaching the band, or both. Write a free band as\n``unit_amount: 0`` rather than by omitting the rate, so \"free\" is\nsomething the price says rather than something it forgot.",
        "properties": {
          "flat_amount": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Flat Amount"
          },
          "unit_amount": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Unit Amount"
          },
          "unit_amount_decimal": {
            "anyOf": [
              {
                "maxLength": 32,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Unit Amount Decimal"
          },
          "up_to": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "const": "inf",
                "type": "string"
              }
            ],
            "title": "Up To"
          }
        },
        "required": [
          "up_to"
        ],
        "title": "PriceTierInput",
        "type": "object"
      },
      "PriceUpdate": {
        "additionalProperties": false,
        "description": "What a price lets you change after it exists.\n\nThe dividing line is Stripe's, and it is the right one: a field that\ndecides **what a past charge was** is immutable, and a field that\ndecides **what happens next** is not. So ``amount_cents``,\n``currency``, ``interval`` and ``usage_type`` have no entry here \u2014\nsubscriptions renew against a price by id, and editing any of them\nwould silently re-price live customers and make an issued invoice\nunreadable. To charge something different, create a new price.\n\nEverything below is forward-looking. ``active`` decides what new\ncheckouts may buy; ``payment_methods`` is read when a checkout opens;\nthe refund fields are read when a cancellation or a refund is\nevaluated. That last point is the useful one: setting\n``refund_on_cancel`` on an existing price covers the customers already\non it, which is the whole reason it is editable rather than\ncreate-only.\n\n``tax_behavior`` is the exception and moves **one way**, matching\nStripe exactly: it can be set while it is ``unspecified`` and never\nchanged again. Flipping it afterwards would restate whether tax was\ninside or on top of an amount somebody has already paid.\n\nEvery field is optional; omitted ones are left alone.",
        "properties": {
          "active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Active"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "maxLength": 500,
                  "type": "string"
                },
                "maxProperties": 50,
                "propertyNames": {
                  "maxLength": 40
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "payment_methods": {
            "anyOf": [
              {
                "items": {
                  "enum": [
                    "creditcard",
                    "directdebit",
                    "ideal",
                    "applepay"
                  ],
                  "type": "string"
                },
                "minItems": 1,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Payment Methods"
          },
          "refund_on_cancel": {
            "anyOf": [
              {
                "enum": [
                  "none",
                  "full",
                  "prorated"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Refund On Cancel"
          },
          "refund_window_initial_days": {
            "anyOf": [
              {
                "maximum": 365.0,
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Refund Window Initial Days"
          },
          "refund_window_renewal_days": {
            "anyOf": [
              {
                "maximum": 365.0,
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Refund Window Renewal Days"
          },
          "tax_behavior": {
            "anyOf": [
              {
                "enum": [
                  "inclusive",
                  "exclusive"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Tax Behavior"
          }
        },
        "title": "PriceUpdate",
        "type": "object"
      },
      "ProductCreate": {
        "additionalProperties": false,
        "properties": {
          "allow_promotion_codes": {
            "default": false,
            "title": "Allow Promotion Codes",
            "type": "boolean"
          },
          "description": {
            "anyOf": [
              {
                "maxLength": 2048,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "marketing_features": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "maxItems": 24,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Marketing Features"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "maxLength": 500,
                  "type": "string"
                },
                "maxProperties": 50,
                "propertyNames": {
                  "maxLength": 40
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "name": {
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "ProductCreate",
        "type": "object"
      },
      "ProductResponse": {
        "properties": {
          "active": {
            "title": "Active",
            "type": "boolean"
          },
          "allow_promotion_codes": {
            "title": "Allow Promotion Codes",
            "type": "boolean"
          },
          "archived_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Archived At"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "marketing_features": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Marketing Features"
          },
          "metadata": {
            "additionalProperties": {
              "type": "string"
            },
            "title": "Metadata",
            "type": "object"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "object": {
            "const": "product",
            "default": "product",
            "title": "Object",
            "type": "string"
          },
          "prices": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/ExpandedPrice"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Prices"
          },
          "stats": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ProductStats"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "name",
          "description",
          "marketing_features",
          "metadata",
          "active",
          "allow_promotion_codes",
          "archived_at"
        ],
        "title": "ProductResponse",
        "type": "object"
      },
      "ProductStats": {
        "description": "What a product is worth right now.\n\n``subscriber_count`` and ``mrr_cents`` count active + trialing\nsubscriptions on any of the product's prices; see\n``services/mrr.py`` for the normalisation and what it deliberately\nleaves out. A display figure, not an accounting one.",
        "properties": {
          "active_price_count": {
            "title": "Active Price Count",
            "type": "integer"
          },
          "currency": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Currency"
          },
          "mrr_cents": {
            "title": "Mrr Cents",
            "type": "integer"
          },
          "object": {
            "const": "product.stats",
            "default": "product.stats",
            "title": "Object",
            "type": "string"
          },
          "subscriber_count": {
            "title": "Subscriber Count",
            "type": "integer"
          }
        },
        "required": [
          "subscriber_count",
          "mrr_cents",
          "currency",
          "active_price_count"
        ],
        "title": "ProductStats",
        "type": "object"
      },
      "ProductUpdate": {
        "additionalProperties": false,
        "properties": {
          "active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Active"
          },
          "allow_promotion_codes": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Allow Promotion Codes"
          },
          "description": {
            "anyOf": [
              {
                "maxLength": 2048,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "marketing_features": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "maxItems": 24,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Marketing Features"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "maxLength": 500,
                  "type": "string"
                },
                "maxProperties": 50,
                "propertyNames": {
                  "maxLength": 40
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "title": "ProductUpdate",
        "type": "object"
      },
      "ProviderPayloadResponse": {
        "properties": {
          "available": {
            "title": "Available",
            "type": "boolean"
          },
          "object": {
            "const": "payment.provider_payload",
            "default": "payment.provider_payload",
            "title": "Object",
            "type": "string"
          },
          "payload": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Payload"
          },
          "provider": {
            "title": "Provider",
            "type": "string"
          },
          "provider_payment_id": {
            "title": "Provider Payment Id",
            "type": "string"
          },
          "unavailable_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Unavailable Reason"
          }
        },
        "required": [
          "available",
          "provider",
          "provider_payment_id",
          "payload",
          "unavailable_reason"
        ],
        "title": "ProviderPayloadResponse",
        "type": "object"
      },
      "ReauthorizationRequest": {
        "additionalProperties": false,
        "properties": {
          "return_url": {
            "format": "uri",
            "maxLength": 2083,
            "minLength": 1,
            "title": "Return Url",
            "type": "string"
          }
        },
        "required": [
          "return_url"
        ],
        "title": "ReauthorizationRequest",
        "type": "object"
      },
      "ReauthorizationResponse": {
        "description": "Returned by ``POST /v1/subscriptions/{id}/reauthorize_payment_method``.\n\nThe Mollie ``checkout_url`` is the URL the tenant must redirect\ntheir customer to. After the customer pays the verification\ncharge, the Mollie webhook updates the subscription's mandate and\nBillKit emits ``subscription.payment_method_updated``.",
        "properties": {
          "checkout_url": {
            "title": "Checkout Url",
            "type": "string"
          },
          "object": {
            "const": "reauthorization",
            "default": "reauthorization",
            "title": "Object",
            "type": "string"
          },
          "operation_id": {
            "title": "Operation Id",
            "type": "string"
          },
          "subscription_id": {
            "title": "Subscription Id",
            "type": "string"
          },
          "verification_amount_cents": {
            "title": "Verification Amount Cents",
            "type": "integer"
          },
          "verification_currency": {
            "title": "Verification Currency",
            "type": "string"
          }
        },
        "required": [
          "subscription_id",
          "operation_id",
          "checkout_url",
          "verification_amount_cents",
          "verification_currency"
        ],
        "title": "ReauthorizationResponse",
        "type": "object"
      },
      "RefundCreateRequest": {
        "additionalProperties": false,
        "properties": {
          "amount_cents": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Amount Cents"
          },
          "one_shot_payment_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "One Shot Payment Id"
          },
          "payment_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Payment Id"
          },
          "reason": {
            "anyOf": [
              {
                "maxLength": 500,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "subscription_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Subscription Id"
          }
        },
        "title": "RefundCreateRequest",
        "type": "object"
      },
      "RefundEligibilityView": {
        "properties": {
          "amount_cents": {
            "title": "Amount Cents",
            "type": "integer"
          },
          "currency": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Currency"
          },
          "days_remaining": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Days Remaining"
          },
          "eligible": {
            "title": "Eligible",
            "type": "boolean"
          },
          "object": {
            "const": "refund_eligibility",
            "default": "refund_eligibility",
            "title": "Object",
            "type": "string"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          }
        },
        "required": [
          "eligible",
          "amount_cents",
          "currency",
          "days_remaining",
          "reason"
        ],
        "title": "RefundEligibilityView",
        "type": "object"
      },
      "RefundResponse": {
        "properties": {
          "amount_cents": {
            "title": "Amount Cents",
            "type": "integer"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "object": {
            "const": "refund",
            "default": "refund",
            "title": "Object",
            "type": "string"
          },
          "one_shot_payment_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "One Shot Payment Id"
          },
          "payment_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Payment Id"
          },
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Reason"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "subscription_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Subscription Id"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "payment_id",
          "one_shot_payment_id",
          "subscription_id",
          "amount_cents",
          "currency",
          "reason",
          "status"
        ],
        "title": "RefundResponse",
        "type": "object"
      },
      "SessionResult": {
        "description": "A completed login. See the module docstring for why it has no token.",
        "properties": {
          "expires_at": {
            "title": "Expires At",
            "type": "integer"
          },
          "object": {
            "const": "operator.session",
            "default": "operator.session",
            "title": "Object",
            "type": "string"
          },
          "operator": {
            "$ref": "#/components/schemas/OperatorInfo"
          },
          "status": {
            "const": "session",
            "default": "session",
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "expires_at",
          "operator"
        ],
        "title": "SessionResult",
        "type": "object"
      },
      "SubscriptionResponse": {
        "properties": {
          "cancel_at_period_end": {
            "title": "Cancel At Period End",
            "type": "boolean"
          },
          "canceled_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Canceled At"
          },
          "cancellation_reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Cancellation Reason"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "current_period_end": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Period End"
          },
          "current_period_start": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Period Start"
          },
          "customer": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ExpandedCustomer"
              },
              {
                "type": "null"
              }
            ]
          },
          "customer_id": {
            "title": "Customer Id",
            "type": "string"
          },
          "dunning_attempts_notified": {
            "title": "Dunning Attempts Notified",
            "type": "integer"
          },
          "dunning_last_notified_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Dunning Last Notified At"
          },
          "dunning_max_attempts": {
            "title": "Dunning Max Attempts",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "last_payment_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Payment At"
          },
          "last_payment_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Payment Id"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "mrr_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mrr Cents"
          },
          "object": {
            "const": "subscription",
            "default": "subscription",
            "title": "Object",
            "type": "string"
          },
          "payment_count": {
            "title": "Payment Count",
            "type": "integer"
          },
          "price": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ExpandedPrice"
              },
              {
                "type": "null"
              }
            ]
          },
          "price_id": {
            "title": "Price Id",
            "type": "string"
          },
          "refund_eligibility": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/RefundEligibilityView"
              },
              {
                "type": "null"
              }
            ]
          },
          "renewal_state": {
            "title": "Renewal State",
            "type": "string"
          },
          "serves_customer": {
            "title": "Serves Customer",
            "type": "boolean"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "trial_end": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial End"
          },
          "trial_start": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Trial Start"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "customer_id",
          "price_id",
          "status",
          "renewal_state",
          "serves_customer",
          "current_period_start",
          "current_period_end",
          "cancel_at_period_end",
          "canceled_at",
          "cancellation_reason",
          "last_payment_id",
          "last_payment_at",
          "payment_count",
          "trial_start",
          "trial_end",
          "dunning_attempts_notified",
          "dunning_last_notified_at",
          "dunning_max_attempts"
        ],
        "title": "SubscriptionResponse",
        "type": "object"
      },
      "TaxRateCreate": {
        "additionalProperties": false,
        "properties": {
          "country_code": {
            "maxLength": 2,
            "minLength": 2,
            "title": "Country Code",
            "type": "string"
          },
          "display_name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Name"
          },
          "inclusive": {
            "default": true,
            "title": "Inclusive",
            "type": "boolean"
          },
          "rate_basis_points": {
            "maximum": 10000.0,
            "minimum": 0.0,
            "title": "Rate Basis Points",
            "type": "integer"
          }
        },
        "required": [
          "country_code",
          "rate_basis_points"
        ],
        "title": "TaxRateCreate",
        "type": "object"
      },
      "TaxRateResponse": {
        "properties": {
          "active": {
            "title": "Active",
            "type": "boolean"
          },
          "country_code": {
            "title": "Country Code",
            "type": "string"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Name"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "inclusive": {
            "title": "Inclusive",
            "type": "boolean"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "object": {
            "const": "tax_rate",
            "default": "tax_rate",
            "title": "Object",
            "type": "string"
          },
          "rate_basis_points": {
            "title": "Rate Basis Points",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "country_code",
          "display_name",
          "rate_basis_points",
          "inclusive",
          "active"
        ],
        "title": "TaxRateResponse",
        "type": "object"
      },
      "TaxRateUpdate": {
        "additionalProperties": false,
        "properties": {
          "active": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Active"
          },
          "display_name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Name"
          },
          "inclusive": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Inclusive"
          },
          "rate_basis_points": {
            "anyOf": [
              {
                "maximum": 10000.0,
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rate Basis Points"
          }
        },
        "title": "TaxRateUpdate",
        "type": "object"
      },
      "TenantBillingProfileResponse": {
        "description": "``GET`` / ``POST /v1/tenant/billing_profile`` shape.\n\n``country_code`` is what is actually stored on the tenant row, so\n``null`` genuinely means \"nobody has ever set this\", the state a\nCLI-provisioned tenant is in. ``effective_country_code`` is the value\nthe reverse-charge check will really compare against on the next\ncharge: the stored code when there is one, otherwise the deployment's\n``BILLKIT_TENANT_DOMESTIC_COUNTRY_CODE`` fallback. Both are returned\nbecause an operator who sees only the fallback cannot tell whether\ntheir account is configured or is silently inheriting someone else's\njurisdiction, and that is exactly the distinction that decides\nwhether their VAT is right.\n\n``vat_id`` is the other half of the same identity: the tenant's own EU\nVAT registration, which is what lets BillKit reverse-charge its own\ninvoice to a cross-border EU tenant instead of refusing to collect it.\nThere is no ``effective_vat_id`` because there is no fallback for it,\nand there should not be: nothing may stand in for a tax registration\nnumber.",
        "properties": {
          "address_line1": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Address Line1"
          },
          "address_line2": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Address Line2"
          },
          "city": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "City"
          },
          "country_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Country Code"
          },
          "effective_country_code": {
            "title": "Effective Country Code",
            "type": "string"
          },
          "object": {
            "const": "tenant_billing_profile",
            "default": "tenant_billing_profile",
            "title": "Object",
            "type": "string"
          },
          "postal_code": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Postal Code"
          },
          "registration_number": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Registration Number"
          },
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          },
          "vat_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Vat Id"
          }
        },
        "required": [
          "tenant_id",
          "country_code",
          "effective_country_code"
        ],
        "title": "TenantBillingProfileResponse",
        "type": "object"
      },
      "TenantBillingProfileUpdate": {
        "additionalProperties": false,
        "description": "``POST /v1/tenant/billing_profile`` body.\n\n``country_code`` is required rather than optional-with-partial-update\nsemantics: there is nothing to leave alone about a jurisdiction, and\nan empty body that silently succeeded would be worse than a 422.\nClearing it back to ``null`` is not offered: a tenant that has stated\nits jurisdiction should not be able to fall back to a deployment-wide\ndefault by accident.\n\n``vat_id`` is the opposite on both counts, and for reasons that are\nfacts about VAT rather than taste:\n\n* It is **optional-with-partial-update**. Omitting it leaves the\n  stored id alone, so a tenant correcting only its country does not\n  have to resend a registration number it was not asked about.\n* Explicit ``null`` **clears** it. Ceasing to be VAT registered is a\n  real event (deregistration, falling under a threshold, a\n  restructure), and a field that can be set once and never emptied\n  would force the tenant to keep asserting a registration it no\n  longer holds.",
        "properties": {
          "address_line1": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Address Line1"
          },
          "address_line2": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Address Line2"
          },
          "city": {
            "anyOf": [
              {
                "maxLength": 128,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "City"
          },
          "country_code": {
            "maxLength": 2,
            "minLength": 2,
            "title": "Country Code",
            "type": "string"
          },
          "postal_code": {
            "anyOf": [
              {
                "maxLength": 32,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Postal Code"
          },
          "registration_number": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Registration Number"
          },
          "vat_id": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Vat Id"
          }
        },
        "required": [
          "country_code"
        ],
        "title": "TenantBillingProfileUpdate",
        "type": "object"
      },
      "TenantCapabilitiesResponse": {
        "description": "Wire shape for ``GET /v1/tenant/capabilities``.\n\nReturned by the read route after blending the tenant's\nconfiguration (``allowed_currencies``,\n``provider_currencies_verified``, refresh timestamp) with the cached\nMollie capabilities view (enabled methods + currencies). Empty\nmethod / currency lists mean the cache has never been populated \u2014\nthe dashboard should display \"verifying\u2026\" until the reaper runs.",
        "properties": {
          "allowed_currencies": {
            "items": {
              "type": "string"
            },
            "title": "Allowed Currencies",
            "type": "array"
          },
          "enabled_currencies": {
            "items": {
              "type": "string"
            },
            "title": "Enabled Currencies",
            "type": "array"
          },
          "enabled_methods": {
            "items": {
              "type": "string"
            },
            "title": "Enabled Methods",
            "type": "array"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "mollie_connected": {
            "title": "Mollie Connected",
            "type": "boolean"
          },
          "object": {
            "const": "tenant_capabilities",
            "default": "tenant_capabilities",
            "title": "Object",
            "type": "string"
          },
          "provider_capabilities_refreshed_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Provider Capabilities Refreshed At"
          },
          "provider_currencies_verified": {
            "title": "Provider Currencies Verified",
            "type": "boolean"
          },
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          }
        },
        "required": [
          "tenant_id",
          "livemode",
          "allowed_currencies",
          "provider_currencies_verified",
          "provider_capabilities_refreshed_at",
          "enabled_methods",
          "enabled_currencies",
          "mollie_connected"
        ],
        "title": "TenantCapabilitiesResponse",
        "type": "object"
      },
      "TenantPortalBrandingResponse": {
        "description": "``GET /v1/tenant/portal_branding`` shape.\n\nMirrors :class:`schemas.portal.PortalTenantBranding` but tagged as\nthe operator-side resource so SDK generators name it differently\n(``TenantPortalBranding`` for the operator surface,\n``PortalTenantBranding`` for what a portal customer sees). The\nrendered values are identical \u2014 both routes ultimately read the\nsame row.",
        "properties": {
          "business_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Business Name"
          },
          "capabilities": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PortalTenantCapabilities"
              },
              {
                "type": "null"
              }
            ]
          },
          "effective_business_name": {
            "default": "",
            "title": "Effective Business Name",
            "type": "string"
          },
          "effective_support_email": {
            "default": "",
            "title": "Effective Support Email",
            "type": "string"
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Logo Url"
          },
          "object": {
            "const": "tenant_portal_branding",
            "default": "tenant_portal_branding",
            "title": "Object",
            "type": "string"
          },
          "support_email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Support Email"
          },
          "theme": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PortalTenantTheme"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "title": "TenantPortalBrandingResponse",
        "type": "object"
      },
      "TenantPortalBrandingUpdate": {
        "additionalProperties": false,
        "description": "``POST /v1/tenant/portal_branding`` body.\n\nEvery field is optional with partial-update semantics: unset\nfields are left alone, fields explicitly set to ``null`` are\ncleared. Reuses :class:`PortalTenantTheme` and\n:class:`PortalTenantCapabilities` from the portal schemas so the\noperator's input and the customer's view are guaranteed to share\na shape \u2014 adding a new theme token surfaces in both places\nwithout a second migration.",
        "properties": {
          "business_name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Business Name"
          },
          "capabilities": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PortalTenantCapabilities"
              },
              {
                "type": "null"
              }
            ]
          },
          "logo_url": {
            "anyOf": [
              {
                "format": "uri",
                "maxLength": 2083,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Logo Url"
          },
          "support_email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Support Email"
          },
          "theme": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PortalTenantTheme"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "title": "TenantPortalBrandingUpdate",
        "type": "object"
      },
      "TenantProviderCredentialResponse": {
        "description": "``POST /v1/tenant/provider_credential`` response.\n\nDoes **not** echo the credential \u2014 returns the identifying triple\nplus a timestamp so the caller can confirm which row was written.",
        "properties": {
          "mode": {
            "enum": [
              "live",
              "test"
            ],
            "title": "Mode",
            "type": "string"
          },
          "object": {
            "const": "tenant_provider_credential",
            "default": "tenant_provider_credential",
            "title": "Object",
            "type": "string"
          },
          "provider": {
            "const": "mollie",
            "title": "Provider",
            "type": "string"
          },
          "rotated_at": {
            "title": "Rotated At",
            "type": "integer"
          },
          "tenant_id": {
            "title": "Tenant Id",
            "type": "string"
          }
        },
        "required": [
          "tenant_id",
          "provider",
          "mode",
          "rotated_at"
        ],
        "title": "TenantProviderCredentialResponse",
        "type": "object"
      },
      "TenantProviderCredentialRotateRequest": {
        "additionalProperties": false,
        "description": "``POST /v1/tenant/provider_credential`` body.\n\nRotates the encrypted credential blob stored in\n:class:`models.TenantProviderCredential` for the (tenant, provider,\nmode) triple. The plaintext is never persisted \u2014 it's encrypted with\n``BILLKIT_MOLLIE_KEY_ENCRYPTION_KEY`` before insert.\n\nCleaner than ``provision_tenant --force`` for the rotation use case:\nno shell access required, idempotent, audit-logged.",
        "properties": {
          "api_key": {
            "maxLength": 128,
            "minLength": 8,
            "title": "Api Key",
            "type": "string"
          },
          "mode": {
            "anyOf": [
              {
                "enum": [
                  "live",
                  "test"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Mode"
          },
          "provider": {
            "const": "mollie",
            "default": "mollie",
            "title": "Provider",
            "type": "string"
          }
        },
        "required": [
          "api_key"
        ],
        "title": "TenantProviderCredentialRotateRequest",
        "type": "object"
      },
      "TestClockAdvance": {
        "additionalProperties": false,
        "properties": {
          "frozen_time": {
            "exclusiveMinimum": 0.0,
            "title": "Frozen Time",
            "type": "integer"
          }
        },
        "required": [
          "frozen_time"
        ],
        "title": "TestClockAdvance",
        "type": "object"
      },
      "TestClockCreate": {
        "additionalProperties": false,
        "properties": {
          "frozen_time": {
            "exclusiveMinimum": 0.0,
            "title": "Frozen Time",
            "type": "integer"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "required": [
          "frozen_time"
        ],
        "title": "TestClockCreate",
        "type": "object"
      },
      "TestClockResponse": {
        "properties": {
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "frozen_time": {
            "title": "Frozen Time",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "object": {
            "const": "test_clock",
            "default": "test_clock",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "name",
          "frozen_time"
        ],
        "title": "TestClockResponse",
        "type": "object"
      },
      "UsageMeterInfo": {
        "properties": {
          "key": {
            "title": "Key",
            "type": "string"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "limit": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Limit"
          },
          "used": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Used"
          }
        },
        "required": [
          "key",
          "label",
          "used",
          "limit"
        ],
        "title": "UsageMeterInfo",
        "type": "object"
      },
      "UsageRecordCreate": {
        "additionalProperties": false,
        "properties": {
          "identifier": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Identifier"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": {
                  "maxLength": 500,
                  "type": "string"
                },
                "maxProperties": 50,
                "propertyNames": {
                  "maxLength": 40
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata"
          },
          "occurred_at": {
            "anyOf": [
              {
                "minimum": 0.0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Occurred At"
          },
          "quantity": {
            "maximum": 1000000.0,
            "minimum": 1.0,
            "title": "Quantity",
            "type": "integer"
          }
        },
        "required": [
          "quantity"
        ],
        "title": "UsageRecordCreate",
        "type": "object"
      },
      "UsageRecordResponse": {
        "properties": {
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "identifier": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Identifier"
          },
          "invoice_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Invoice Id"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "metadata": {
            "additionalProperties": {
              "type": "string"
            },
            "title": "Metadata",
            "type": "object"
          },
          "object": {
            "const": "usage_record",
            "default": "usage_record",
            "title": "Object",
            "type": "string"
          },
          "occurred_at": {
            "title": "Occurred At",
            "type": "integer"
          },
          "quantity": {
            "title": "Quantity",
            "type": "integer"
          },
          "subscription_id": {
            "title": "Subscription Id",
            "type": "string"
          },
          "written_off_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Written Off At"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "subscription_id",
          "quantity",
          "occurred_at",
          "invoice_id",
          "identifier",
          "written_off_at",
          "metadata"
        ],
        "title": "UsageRecordResponse",
        "type": "object"
      },
      "UsageSummaryResponse": {
        "description": "What the next period close will bill, and whether it will charge.",
        "properties": {
          "currency": {
            "title": "Currency",
            "type": "string"
          },
          "gross_cents": {
            "title": "Gross Cents",
            "type": "integer"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "minimum_charge_cents": {
            "title": "Minimum Charge Cents",
            "type": "integer"
          },
          "net_cents": {
            "title": "Net Cents",
            "type": "integer"
          },
          "object": {
            "const": "usage_summary",
            "default": "usage_summary",
            "title": "Object",
            "type": "string"
          },
          "open_invoice_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Open Invoice Id"
          },
          "pending_quantity": {
            "title": "Pending Quantity",
            "type": "integer"
          },
          "pending_record_count": {
            "title": "Pending Record Count",
            "type": "integer"
          },
          "period_end": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Period End"
          },
          "period_start": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Period Start"
          },
          "subscription_id": {
            "title": "Subscription Id",
            "type": "string"
          },
          "tax_cents": {
            "title": "Tax Cents",
            "type": "integer"
          },
          "will_charge": {
            "title": "Will Charge",
            "type": "boolean"
          }
        },
        "required": [
          "livemode",
          "subscription_id",
          "period_start",
          "period_end",
          "currency",
          "pending_quantity",
          "pending_record_count",
          "net_cents",
          "tax_cents",
          "gross_cents",
          "will_charge",
          "minimum_charge_cents",
          "open_invoice_id"
        ],
        "title": "UsageSummaryResponse",
        "type": "object"
      },
      "ValidationError": {
        "properties": {
          "ctx": {
            "title": "Context",
            "type": "object"
          },
          "input": {
            "title": "Input"
          },
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "title": "Location",
            "type": "array"
          },
          "msg": {
            "title": "Message",
            "type": "string"
          },
          "type": {
            "title": "Error Type",
            "type": "string"
          }
        },
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError",
        "type": "object"
      },
      "WebhookDeliveryResponse": {
        "description": "One row of the per-event-per-endpoint delivery ledger.\n\nSurfaces the worker's view to the tenant so they can debug a\nfailing receiver without DB access. Body excerpt is truncated to\n2KB at row-insert time so a misbehaving receiver can't bloat the\nlisting payload.",
        "properties": {
          "attempt_count": {
            "title": "Attempt Count",
            "type": "integer"
          },
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "delivered_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Delivered At"
          },
          "endpoint_id": {
            "title": "Endpoint Id",
            "type": "string"
          },
          "event_id": {
            "title": "Event Id",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "last_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Error"
          },
          "last_response_body_excerpt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Response Body Excerpt"
          },
          "last_response_code": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Response Code"
          },
          "next_attempt_at": {
            "title": "Next Attempt At",
            "type": "integer"
          },
          "object": {
            "const": "webhook_delivery",
            "default": "webhook_delivery",
            "title": "Object",
            "type": "string"
          },
          "status": {
            "enum": [
              "pending",
              "delivered",
              "failed"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "id",
          "event_id",
          "endpoint_id",
          "status",
          "attempt_count",
          "next_attempt_at",
          "created"
        ],
        "title": "WebhookDeliveryResponse",
        "type": "object"
      },
      "WebhookEndpointCreate": {
        "additionalProperties": false,
        "properties": {
          "description": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "enabled_events": {
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "title": "Enabled Events",
            "type": "array"
          },
          "url": {
            "format": "uri",
            "maxLength": 2083,
            "minLength": 1,
            "title": "Url",
            "type": "string"
          }
        },
        "required": [
          "url"
        ],
        "title": "WebhookEndpointCreate",
        "type": "object"
      },
      "WebhookEndpointResponse": {
        "properties": {
          "created": {
            "title": "Created",
            "type": "integer"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "enabled_events": {
            "items": {
              "type": "string"
            },
            "title": "Enabled Events",
            "type": "array"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "livemode": {
            "title": "Livemode",
            "type": "boolean"
          },
          "object": {
            "const": "webhook_endpoint",
            "default": "webhook_endpoint",
            "title": "Object",
            "type": "string"
          },
          "previous_secret_fingerprint": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Previous Secret Fingerprint"
          },
          "previous_secret_retired_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Previous Secret Retired At"
          },
          "secret": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Secret"
          },
          "secret_fingerprint": {
            "title": "Secret Fingerprint",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "url": {
            "title": "Url",
            "type": "string"
          }
        },
        "required": [
          "id",
          "created",
          "livemode",
          "url",
          "enabled_events",
          "status",
          "description",
          "secret_fingerprint"
        ],
        "title": "WebhookEndpointResponse",
        "type": "object"
      },
      "WebhookEndpointUpdate": {
        "additionalProperties": false,
        "properties": {
          "description": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description"
          },
          "enabled_events": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "minItems": 1,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enabled Events"
          },
          "status": {
            "anyOf": [
              {
                "enum": [
                  "enabled",
                  "disabled"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status"
          },
          "url": {
            "anyOf": [
              {
                "format": "uri",
                "maxLength": 2083,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Url"
          }
        },
        "title": "WebhookEndpointUpdate",
        "type": "object"
      },
      "_AuthorizeResponse": {
        "additionalProperties": false,
        "properties": {
          "authorize_url": {
            "title": "Authorize Url",
            "type": "string"
          },
          "object": {
            "const": "console.onboarding.mollie_authorize",
            "default": "console.onboarding.mollie_authorize",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "authorize_url"
        ],
        "title": "_AuthorizeResponse",
        "type": "object"
      },
      "_Caveat": {
        "properties": {
          "code": {
            "title": "Code",
            "type": "string"
          },
          "count": {
            "title": "Count",
            "type": "integer"
          },
          "label": {
            "title": "Label",
            "type": "string"
          },
          "severity": {
            "title": "Severity",
            "type": "string"
          }
        },
        "required": [
          "code",
          "label",
          "count",
          "severity"
        ],
        "title": "_Caveat",
        "type": "object"
      },
      "_ConnectBody": {
        "additionalProperties": false,
        "properties": {
          "restricted_key": {
            "maxLength": 256,
            "minLength": 12,
            "title": "Restricted Key",
            "type": "string"
          }
        },
        "required": [
          "restricted_key"
        ],
        "title": "_ConnectBody",
        "type": "object"
      },
      "_ConnectResponse": {
        "properties": {
          "expires_at": {
            "title": "Expires At",
            "type": "integer"
          },
          "key_last4": {
            "title": "Key Last4",
            "type": "string"
          },
          "mode": {
            "title": "Mode",
            "type": "string"
          },
          "object": {
            "const": "stripe_import.session",
            "default": "stripe_import.session",
            "title": "Object",
            "type": "string"
          },
          "scan_token": {
            "title": "Scan Token",
            "type": "string"
          }
        },
        "required": [
          "scan_token",
          "expires_at",
          "key_last4",
          "mode"
        ],
        "title": "_ConnectResponse",
        "type": "object"
      },
      "_CustomerRow": {
        "properties": {
          "amount_cents": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Amount Cents"
          },
          "currency": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Currency"
          },
          "email": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "stripe_id": {
            "title": "Stripe Id",
            "type": "string"
          },
          "subscription_label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Subscription Label"
          }
        },
        "required": [
          "stripe_id",
          "email",
          "name",
          "subscription_label",
          "amount_cents",
          "currency",
          "status"
        ],
        "title": "_CustomerRow",
        "type": "object"
      },
      "_CustomersResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/_CustomerRow"
            },
            "title": "Data",
            "type": "array"
          },
          "has_more": {
            "title": "Has More",
            "type": "boolean"
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor"
          },
          "object": {
            "const": "list",
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "title": "_CustomersResponse",
        "type": "object"
      },
      "_DryRunResponse": {
        "properties": {
          "caveats": {
            "items": {
              "$ref": "#/components/schemas/_Caveat"
            },
            "title": "Caveats",
            "type": "array"
          },
          "customers": {
            "title": "Customers",
            "type": "integer"
          },
          "existing_collisions": {
            "title": "Existing Collisions",
            "type": "integer"
          },
          "object": {
            "const": "stripe_import.dry_run",
            "default": "stripe_import.dry_run",
            "title": "Object",
            "type": "string"
          },
          "prices": {
            "title": "Prices",
            "type": "integer"
          },
          "products": {
            "title": "Products",
            "type": "integer"
          },
          "reauth_required": {
            "title": "Reauth Required",
            "type": "integer"
          },
          "subscriptions": {
            "title": "Subscriptions",
            "type": "integer"
          },
          "unsupported_subscriptions": {
            "title": "Unsupported Subscriptions",
            "type": "integer"
          }
        },
        "required": [
          "customers",
          "subscriptions",
          "products",
          "prices",
          "reauth_required",
          "unsupported_subscriptions",
          "existing_collisions",
          "caveats"
        ],
        "title": "_DryRunResponse",
        "type": "object"
      },
      "_FactorsResponse": {
        "properties": {
          "object": {
            "const": "operator.factors",
            "default": "operator.factors",
            "title": "Object",
            "type": "string"
          },
          "passkey_count": {
            "title": "Passkey Count",
            "type": "integer"
          },
          "password_set": {
            "title": "Password Set",
            "type": "boolean"
          },
          "recovery_codes_remaining": {
            "title": "Recovery Codes Remaining",
            "type": "integer"
          },
          "totp_enabled": {
            "title": "Totp Enabled",
            "type": "boolean"
          }
        },
        "required": [
          "password_set",
          "totp_enabled",
          "recovery_codes_remaining",
          "passkey_count"
        ],
        "title": "_FactorsResponse",
        "type": "object"
      },
      "_InviteBody": {
        "additionalProperties": false,
        "properties": {
          "email": {
            "format": "email",
            "title": "Email",
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "role": {
            "const": "admin",
            "default": "admin",
            "title": "Role",
            "type": "string"
          }
        },
        "required": [
          "email"
        ],
        "title": "_InviteBody",
        "type": "object"
      },
      "_InviteResponse": {
        "additionalProperties": false,
        "properties": {
          "created_at": {
            "title": "Created At",
            "type": "integer"
          },
          "email": {
            "title": "Email",
            "type": "string"
          },
          "expires_at": {
            "title": "Expires At",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "object": {
            "const": "console.team_invite",
            "default": "console.team_invite",
            "title": "Object",
            "type": "string"
          },
          "role": {
            "title": "Role",
            "type": "string"
          }
        },
        "required": [
          "id",
          "email",
          "name",
          "role",
          "created_at",
          "expires_at"
        ],
        "title": "_InviteResponse",
        "type": "object"
      },
      "_JobResponse": {
        "properties": {
          "created_customers": {
            "title": "Created Customers",
            "type": "integer"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Error"
          },
          "events": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Events",
            "type": "array"
          },
          "finished_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Finished At"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "object": {
            "const": "stripe_import.job",
            "default": "stripe_import.job",
            "title": "Object",
            "type": "string"
          },
          "prices_created": {
            "title": "Prices Created",
            "type": "integer"
          },
          "processed_customers": {
            "title": "Processed Customers",
            "type": "integer"
          },
          "products_created": {
            "title": "Products Created",
            "type": "integer"
          },
          "reauth_required": {
            "title": "Reauth Required",
            "type": "integer"
          },
          "skipped_existing": {
            "title": "Skipped Existing",
            "type": "integer"
          },
          "status": {
            "title": "Status",
            "type": "string"
          },
          "subscriptions_created": {
            "title": "Subscriptions Created",
            "type": "integer"
          },
          "total_customers": {
            "title": "Total Customers",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "status",
          "total_customers",
          "processed_customers",
          "created_customers",
          "skipped_existing",
          "products_created",
          "prices_created",
          "subscriptions_created",
          "reauth_required",
          "events",
          "error",
          "finished_at"
        ],
        "title": "_JobResponse",
        "type": "object"
      },
      "_LoginBody": {
        "additionalProperties": false,
        "properties": {
          "email": {
            "format": "email",
            "title": "Email",
            "type": "string"
          },
          "password": {
            "maxLength": 1024,
            "minLength": 1,
            "title": "Password",
            "type": "string"
          }
        },
        "required": [
          "email",
          "password"
        ],
        "title": "_LoginBody",
        "type": "object"
      },
      "_MeResponse": {
        "properties": {
          "object": {
            "const": "operator",
            "default": "operator",
            "title": "Object",
            "type": "string"
          },
          "operator": {
            "$ref": "#/components/schemas/OperatorInfo"
          },
          "session": {
            "$ref": "#/components/schemas/_SessionInfo"
          }
        },
        "required": [
          "operator",
          "session"
        ],
        "title": "_MeResponse",
        "type": "object"
      },
      "_MemberResponse": {
        "additionalProperties": false,
        "properties": {
          "created_at": {
            "title": "Created At",
            "type": "integer"
          },
          "disabled": {
            "title": "Disabled",
            "type": "boolean"
          },
          "email": {
            "title": "Email",
            "type": "string"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "is_self": {
            "title": "Is Self",
            "type": "boolean"
          },
          "last_login_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Login At"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          },
          "object": {
            "const": "console.team_member",
            "default": "console.team_member",
            "title": "Object",
            "type": "string"
          },
          "role": {
            "title": "Role",
            "type": "string"
          }
        },
        "required": [
          "id",
          "email",
          "name",
          "role",
          "is_self",
          "disabled",
          "created_at",
          "last_login_at"
        ],
        "title": "_MemberResponse",
        "type": "object"
      },
      "_MetricPoint": {
        "description": "One stat card's data. Client renders the value + delta chip +\nsparkline off this shape. Delta is absolute (cents for money,\ncount for scalar); percentage renders on the client side so we\ndon't have to pick a rounding policy in the API.",
        "properties": {
          "delta": {
            "title": "Delta",
            "type": "integer"
          },
          "sparkline": {
            "items": {
              "type": "integer"
            },
            "title": "Sparkline",
            "type": "array"
          },
          "value": {
            "title": "Value",
            "type": "integer"
          }
        },
        "required": [
          "value",
          "delta",
          "sparkline"
        ],
        "title": "_MetricPoint",
        "type": "object"
      },
      "_MfaVerifyBody": {
        "additionalProperties": false,
        "properties": {
          "challenge_token": {
            "maxLength": 128,
            "minLength": 1,
            "title": "Challenge Token",
            "type": "string"
          },
          "code": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Code",
            "type": "string"
          }
        },
        "required": [
          "challenge_token",
          "code"
        ],
        "title": "_MfaVerifyBody",
        "type": "object"
      },
      "_NotifyOwnerBody": {
        "additionalProperties": false,
        "properties": {
          "action": {
            "maxLength": 200,
            "minLength": 1,
            "title": "Action",
            "type": "string"
          },
          "required_role": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Required Role",
            "type": "string"
          }
        },
        "required": [
          "required_role",
          "action"
        ],
        "title": "_NotifyOwnerBody",
        "type": "object"
      },
      "_PasskeyAuthOptionsBody": {
        "additionalProperties": false,
        "properties": {
          "email": {
            "anyOf": [
              {
                "format": "email",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Email"
          }
        },
        "title": "_PasskeyAuthOptionsBody",
        "type": "object"
      },
      "_PasskeyAuthOptionsResponse": {
        "properties": {
          "challenge_token": {
            "title": "Challenge Token",
            "type": "string"
          },
          "object": {
            "const": "operator.passkey_options",
            "default": "operator.passkey_options",
            "title": "Object",
            "type": "string"
          },
          "options": {
            "additionalProperties": true,
            "title": "Options",
            "type": "object"
          }
        },
        "required": [
          "challenge_token",
          "options"
        ],
        "title": "_PasskeyAuthOptionsResponse",
        "type": "object"
      },
      "_PasskeyAuthVerifyBody": {
        "additionalProperties": false,
        "properties": {
          "challenge_token": {
            "maxLength": 128,
            "minLength": 1,
            "title": "Challenge Token",
            "type": "string"
          },
          "credential": {
            "additionalProperties": true,
            "title": "Credential",
            "type": "object"
          }
        },
        "required": [
          "challenge_token",
          "credential"
        ],
        "title": "_PasskeyAuthVerifyBody",
        "type": "object"
      },
      "_PasskeyListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/_PasskeyView"
            },
            "title": "Data",
            "type": "array"
          },
          "object": {
            "const": "list",
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "_PasskeyListResponse",
        "type": "object"
      },
      "_PasskeyRegisterOptionsBody": {
        "additionalProperties": false,
        "properties": {
          "step_up_challenge_token": {
            "anyOf": [
              {
                "maxLength": 128,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Step Up Challenge Token"
          },
          "step_up_code": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Step Up Code"
          },
          "step_up_credential": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Step Up Credential"
          },
          "step_up_password": {
            "anyOf": [
              {
                "maxLength": 1024,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Step Up Password"
          }
        },
        "title": "_PasskeyRegisterOptionsBody",
        "type": "object"
      },
      "_PasskeyRegisterOptionsResponse": {
        "properties": {
          "challenge_token": {
            "title": "Challenge Token",
            "type": "string"
          },
          "object": {
            "const": "operator.passkey_options",
            "default": "operator.passkey_options",
            "title": "Object",
            "type": "string"
          },
          "options": {
            "additionalProperties": true,
            "title": "Options",
            "type": "object"
          }
        },
        "required": [
          "challenge_token",
          "options"
        ],
        "title": "_PasskeyRegisterOptionsResponse",
        "type": "object"
      },
      "_PasskeyRegisterVerifyBody": {
        "additionalProperties": false,
        "properties": {
          "challenge_token": {
            "maxLength": 128,
            "minLength": 1,
            "title": "Challenge Token",
            "type": "string"
          },
          "credential": {
            "additionalProperties": true,
            "title": "Credential",
            "type": "object"
          },
          "name": {
            "anyOf": [
              {
                "maxLength": 120,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "required": [
          "challenge_token",
          "credential"
        ],
        "title": "_PasskeyRegisterVerifyBody",
        "type": "object"
      },
      "_PasskeyView": {
        "properties": {
          "created_at": {
            "title": "Created At",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Name"
          }
        },
        "required": [
          "id",
          "name",
          "created_at",
          "last_used_at"
        ],
        "title": "_PasskeyView",
        "type": "object"
      },
      "_RecoveryCodesResponse": {
        "properties": {
          "object": {
            "const": "operator.recovery_codes",
            "default": "operator.recovery_codes",
            "title": "Object",
            "type": "string"
          },
          "recovery_codes": {
            "items": {
              "type": "string"
            },
            "title": "Recovery Codes",
            "type": "array"
          }
        },
        "required": [
          "recovery_codes"
        ],
        "title": "_RecoveryCodesResponse",
        "type": "object"
      },
      "_RequestLoginLinkBody": {
        "additionalProperties": false,
        "properties": {
          "email": {
            "format": "email",
            "title": "Email",
            "type": "string"
          }
        },
        "required": [
          "email"
        ],
        "title": "_RequestLoginLinkBody",
        "type": "object"
      },
      "_RevokeOthersResponse": {
        "properties": {
          "revoked": {
            "title": "Revoked",
            "type": "integer"
          },
          "status": {
            "const": "ok",
            "default": "ok",
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "revoked"
        ],
        "title": "_RevokeOthersResponse",
        "type": "object"
      },
      "_SeatsResponse": {
        "additionalProperties": false,
        "properties": {
          "limit": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Limit"
          },
          "pending": {
            "title": "Pending",
            "type": "integer"
          },
          "used": {
            "title": "Used",
            "type": "integer"
          }
        },
        "required": [
          "used",
          "pending",
          "limit"
        ],
        "title": "_SeatsResponse",
        "type": "object"
      },
      "_SelectionBody": {
        "additionalProperties": false,
        "properties": {
          "customer_ids": {
            "items": {
              "type": "string"
            },
            "maxItems": 5000,
            "title": "Customer Ids",
            "type": "array"
          },
          "scan_token": {
            "maxLength": 128,
            "minLength": 8,
            "title": "Scan Token",
            "type": "string"
          },
          "select_all": {
            "default": false,
            "title": "Select All",
            "type": "boolean"
          }
        },
        "required": [
          "scan_token"
        ],
        "title": "_SelectionBody",
        "type": "object"
      },
      "_SessionInfo": {
        "description": "Session metadata for ``GET /me``.\n\nStays local: unlike the login-result shapes in\n:mod:`schemas.operator_auth`, nothing else answers with this \u2014 the\nlogin routes deliberately do not describe the session they minted\nbeyond its expiry.",
        "properties": {
          "absolute_expires_at": {
            "title": "Absolute Expires At",
            "type": "integer"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "sliding_expires_at": {
            "title": "Sliding Expires At",
            "type": "integer"
          }
        },
        "required": [
          "id",
          "absolute_expires_at",
          "sliding_expires_at",
          "last_used_at"
        ],
        "title": "_SessionInfo",
        "type": "object"
      },
      "_SessionListItem": {
        "description": "One live operator session as rendered in the console Security tab.\n\n``current`` flags the caller's own session (the one that can't be\nrevoked from the row UI \u2014 you sign it out via logout). ``user_agent``\nand ``ip_at_creation`` are the raw audit fields captured at mint; the\nconsole parses the UA into a friendly device label and shows the IP\nverbatim (BillKit stores no geo-IP).",
        "properties": {
          "absolute_expires_at": {
            "title": "Absolute Expires At",
            "type": "integer"
          },
          "created_at": {
            "title": "Created At",
            "type": "integer"
          },
          "current": {
            "title": "Current",
            "type": "boolean"
          },
          "id": {
            "title": "Id",
            "type": "string"
          },
          "ip_at_creation": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ip At Creation"
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Used At"
          },
          "sliding_expires_at": {
            "title": "Sliding Expires At",
            "type": "integer"
          },
          "user_agent": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "User Agent"
          }
        },
        "required": [
          "id",
          "current",
          "user_agent",
          "ip_at_creation",
          "created_at",
          "last_used_at",
          "absolute_expires_at",
          "sliding_expires_at"
        ],
        "title": "_SessionListItem",
        "type": "object"
      },
      "_SessionListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/_SessionListItem"
            },
            "title": "Data",
            "type": "array"
          },
          "object": {
            "const": "list",
            "default": "list",
            "title": "Object",
            "type": "string"
          }
        },
        "required": [
          "data"
        ],
        "title": "_SessionListResponse",
        "type": "object"
      },
      "_SetPasswordBody": {
        "additionalProperties": false,
        "properties": {
          "current_password": {
            "anyOf": [
              {
                "maxLength": 1024,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Current Password"
          },
          "new_password": {
            "maxLength": 1024,
            "minLength": 1,
            "title": "New Password",
            "type": "string"
          },
          "step_up_challenge_token": {
            "anyOf": [
              {
                "maxLength": 128,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Step Up Challenge Token"
          },
          "step_up_code": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Step Up Code"
          },
          "step_up_credential": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Step Up Credential"
          },
          "step_up_password": {
            "anyOf": [
              {
                "maxLength": 1024,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Step Up Password"
          }
        },
        "required": [
          "new_password"
        ],
        "title": "_SetPasswordBody",
        "type": "object"
      },
      "_SignUpBody": {
        "additionalProperties": false,
        "properties": {
          "business_name": {
            "maxLength": 255,
            "minLength": 1,
            "title": "Business Name",
            "type": "string"
          },
          "country_code": {
            "maxLength": 2,
            "minLength": 2,
            "title": "Country Code",
            "type": "string"
          },
          "logo_url": {
            "anyOf": [
              {
                "maxLength": 2048,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Logo Url"
          },
          "owner_email": {
            "format": "email",
            "title": "Owner Email",
            "type": "string"
          },
          "owner_name": {
            "anyOf": [
              {
                "maxLength": 255,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Owner Name"
          },
          "primary_color": {
            "anyOf": [
              {
                "maxLength": 7,
                "minLength": 7,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Primary Color"
          },
          "vat_id": {
            "anyOf": [
              {
                "maxLength": 64,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Vat Id"
          }
        },
        "required": [
          "business_name",
          "country_code",
          "owner_email"
        ],
        "title": "_SignUpBody",
        "type": "object"
      },
      "_SignUpResponse": {
        "properties": {
          "object": {
            "const": "tenant.signup",
            "default": "tenant.signup",
            "title": "Object",
            "type": "string"
          },
          "status": {
            "const": "ok",
            "default": "ok",
            "title": "Status",
            "type": "string"
          },
          "tenant": {
            "$ref": "#/components/schemas/_SignUpTenantInfo"
          }
        },
        "required": [
          "tenant"
        ],
        "title": "_SignUpResponse",
        "type": "object"
      },
      "_SignUpTenantInfo": {
        "properties": {
          "id": {
            "title": "Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name"
        ],
        "title": "_SignUpTenantInfo",
        "type": "object"
      },
      "_StatusResponse": {
        "properties": {
          "status": {
            "const": "ok",
            "default": "ok",
            "title": "Status",
            "type": "string"
          }
        },
        "title": "_StatusResponse",
        "type": "object"
      },
      "_TeamResponse": {
        "additionalProperties": false,
        "properties": {
          "invites": {
            "items": {
              "$ref": "#/components/schemas/_InviteResponse"
            },
            "title": "Invites",
            "type": "array"
          },
          "members": {
            "items": {
              "$ref": "#/components/schemas/_MemberResponse"
            },
            "title": "Members",
            "type": "array"
          },
          "object": {
            "const": "console.team",
            "default": "console.team",
            "title": "Object",
            "type": "string"
          },
          "seats": {
            "$ref": "#/components/schemas/_SeatsResponse"
          }
        },
        "required": [
          "members",
          "invites",
          "seats"
        ],
        "title": "_TeamResponse",
        "type": "object"
      },
      "_TotpConfirmBody": {
        "additionalProperties": false,
        "properties": {
          "code": {
            "maxLength": 16,
            "minLength": 1,
            "title": "Code",
            "type": "string"
          }
        },
        "required": [
          "code"
        ],
        "title": "_TotpConfirmBody",
        "type": "object"
      },
      "_TotpDisableBody": {
        "additionalProperties": false,
        "properties": {
          "code": {
            "maxLength": 64,
            "minLength": 1,
            "title": "Code",
            "type": "string"
          }
        },
        "required": [
          "code"
        ],
        "title": "_TotpDisableBody",
        "type": "object"
      },
      "_TotpEnrollResponse": {
        "properties": {
          "object": {
            "const": "operator.totp_enrollment",
            "default": "operator.totp_enrollment",
            "title": "Object",
            "type": "string"
          },
          "otpauth_uri": {
            "title": "Otpauth Uri",
            "type": "string"
          },
          "secret": {
            "title": "Secret",
            "type": "string"
          }
        },
        "required": [
          "secret",
          "otpauth_uri"
        ],
        "title": "_TotpEnrollResponse",
        "type": "object"
      },
      "_VerifyBody": {
        "additionalProperties": false,
        "properties": {
          "token": {
            "maxLength": 256,
            "minLength": 8,
            "title": "Token",
            "type": "string"
          }
        },
        "required": [
          "token"
        ],
        "title": "_VerifyBody",
        "type": "object"
      }
    }
  },
  "info": {
    "contact": {
      "name": "BillKit",
      "url": "https://billkit.eu/"
    },
    "description": "Stripe-Billing\u2013shape multi-tenant SaaS API on Mollie. Customers, prices, subscriptions, checkout sessions, payments, refunds, coupons, tax rates, invoices, signed outbound webhooks. Idempotency-key semantics and object-ID prefixes mirror Stripe; credentials deliberately do not, so BillKit keys (bk_live_/bk_test_) are distinguishable by secret scanners. Backed by Mollie for card + SEPA Direct Debit recurring. This OpenAPI document is published under Apache-2.0 so you can generate and ship a client from it; the BillKit service itself is commercial and is not covered by that licence.",
    "license": {
      "identifier": "Apache-2.0",
      "name": "Apache License 2.0"
    },
    "title": "BillKit",
    "version": "0.1.0"
  },
  "openapi": "3.1.0",
  "paths": {
    "/healthz": {
      "get": {
        "operationId": "healthz",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "title": "Response Healthz",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Healthz",
        "tags": [
          "meta"
        ]
      }
    },
    "/internal/webhooks/mollie/{route_id}": {
      "post": {
        "operationId": "mollie_webhook",
        "parameters": [
          {
            "in": "path",
            "name": "route_id",
            "required": true,
            "schema": {
              "title": "Route Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Mollie Webhook",
        "tags": [
          "internal"
        ]
      }
    },
    "/readyz": {
      "get": {
        "operationId": "readyz",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "title": "Response Readyz",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Readyz",
        "tags": [
          "meta"
        ]
      }
    },
    "/v1/account/activation": {
      "get": {
        "operationId": "get_activation",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActivationResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Activation",
        "tags": [
          "account_onboarding"
        ]
      }
    },
    "/v1/account/attention": {
      "get": {
        "description": "What needs looking at, worst first.\n\nDrives the console Home panel of the same name. Operational problems\n(past-due subscriptions, open disputes, dead webhook deliveries) come\nbefore unfinished setup, and an account with neither gets an empty\nlist \u2014 which is the point. Everything is derived on read, so there is\nnothing to dismiss and nothing that can go stale.",
        "operationId": "get_attention",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AttentionResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Attention",
        "tags": [
          "account_onboarding"
        ]
      }
    },
    "/v1/account/billing": {
      "get": {
        "description": "Return the caller's tenant's BillKit subscription + usage.\n\nLazily creates a free/trialing meta-subscription for a tenant that\nlacks one (defensive \u2014 the migration backfills existing tenants and\nsignup creates new ones), so the commit persists that row.",
        "operationId": "get_account_billing",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountBillingResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Account Billing",
        "tags": [
          "account_billing"
        ]
      }
    },
    "/v1/account/billing/authorize": {
      "post": {
        "description": "Start the \"authorize BillKit to bill you\" flow (meta-billing 3b).\n\nCreates a ``sequenceType=first`` verification payment on BillKit's own\nMollie account and returns Mollie's checkout URL for the operator to\ncomplete; the mandate is captured asynchronously by the platform\nwebhook. 501s when platform collection isn't configured on this\ndeployment (no platform key / webhook route); 409s when the tenant is\nalready authorized. Commits so the platform customer id persists.",
        "operationId": "authorize_account_billing",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformAuthorizeResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Authorize Account Billing",
        "tags": [
          "account_billing"
        ]
      }
    },
    "/v1/account/billing/change_plan": {
      "post": {
        "description": "Change the caller's tenant's BillKit plan (meta-billing plan change).\n\nImmediate + arrears-honest: the plan switches now, the billing cycle is\npreserved, and any elapsed old-plan time this period is billed at the old\nrate on the next period-end collection (a mid-period upgrade bills the delta\nin arrears, never in advance; a downgrade simply bills less). Refuses a\npaid target with no captured mandate (409 \u2014 authorize first), and a\ncanceled / past_due / period-due subscription (409 \u2014 settle first). 404s a\nmissing target; 400s the same plan or a currency/interval mismatch.\nReturns the refreshed billing view.",
        "operationId": "change_account_plan",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePlanRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountBillingResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Change Account Plan",
        "tags": [
          "account_billing"
        ]
      }
    },
    "/v1/account/billing/change_plan/preview": {
      "post": {
        "description": "Money-honest quote for a plan change \u2014 no charge, no plan switch.\n\nBillKit bills in arrears, so a mid-period change bills nothing now: the\nquote reports what the current period will total at its end (the blended\nold+new rate) and the steady-state next-period price, plus why the change\nwould be blocked / need authorization. 404s a missing/inactive target;\n400s the same plan or a currency/interval mismatch.",
        "operationId": "preview_account_plan_change",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ChangePlanRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetaPlanChangePreview"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Preview Account Plan Change",
        "tags": [
          "account_billing"
        ]
      }
    },
    "/v1/account/billing/plans": {
      "get": {
        "description": "List the active BillKit plans the operator can switch to.\n\nThe plan-picker menu for Settings \u2192 Billing. Read-only \u2014 the caller's\ncurrent plan is on ``GET /v1/account/billing``.",
        "operationId": "list_account_plans",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetaPlanListResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Account Plans",
        "tags": [
          "account_billing"
        ]
      }
    },
    "/v1/account/domain": {
      "delete": {
        "operationId": "delete_domain_route",
        "responses": {
          "204": {
            "description": "Successful Response"
          }
        },
        "summary": "Delete Domain Route",
        "tags": [
          "account_onboarding"
        ]
      },
      "get": {
        "operationId": "get_domain_route",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Domain Route",
        "tags": [
          "account_onboarding"
        ]
      },
      "put": {
        "operationId": "put_domain_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DomainCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Put Domain Route",
        "tags": [
          "account_onboarding"
        ]
      }
    },
    "/v1/account/domain/verify": {
      "post": {
        "operationId": "verify_domain_route",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DomainResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Verify Domain Route",
        "tags": [
          "account_onboarding"
        ]
      }
    },
    "/v1/account/go_live": {
      "get": {
        "operationId": "get_go_live",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GoLiveResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Go Live",
        "tags": [
          "account_onboarding"
        ]
      },
      "post": {
        "operationId": "post_go_live",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GoLiveResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Post Go Live",
        "tags": [
          "account_onboarding"
        ]
      }
    },
    "/v1/account/invoices": {
      "get": {
        "description": "List the caller's tenant's BillKit invoices, most recent first.\n\nLazily materialises the current period's invoice (paid plans only \u2014\na free tenant owes nothing, so its history is honestly empty), then\ncommits so the issued row persists. Slice 2 is generation only: rows\nare ``open`` and uncollected.",
        "operationId": "list_account_invoices",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetaInvoiceListResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Account Invoices",
        "tags": [
          "account_billing"
        ]
      }
    },
    "/v1/account/invoices/{invoice_id}": {
      "get": {
        "description": "Fetch one BillKit invoice for the caller's tenant.",
        "operationId": "get_account_invoice",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetaInvoiceInfo"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Account Invoice",
        "tags": [
          "account_billing"
        ]
      }
    },
    "/v1/account/invoices/{invoice_id}/collect": {
      "post": {
        "description": "Collect one open BillKit invoice on BillKit's own account (slice 3c).\n\nOperator-initiated \"Pay now\": finalises the invoice VAT (B2B\nreverse-charge) and creates a ``sequenceType=recurring`` charge against\nthe tenant's authorized platform mandate. The invoice stays ``open``\nuntil the platform webhook confirms the charge paid \u2014 this returns the\ninvoice with its finalised totals, not a ``paid`` status. 501s when the\nplatform account isn't configured; 409s when the tenant isn't yet\nauthorized or the invoice isn't open; 422s when the VAT treatment can't\nbe determined honestly (missing country / unverifiable VAT id).",
        "operationId": "collect_account_invoice",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetaInvoiceInfo"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Collect Account Invoice",
        "tags": [
          "account_billing"
        ]
      }
    },
    "/v1/account/invoices/{invoice_id}/pdf": {
      "get": {
        "description": "Render + stream the BillKit invoice PDF for the caller's tenant.\n\nReuses the tenant-invoice WeasyPrint renderer with BillKit as the\nissuer. Rendered on-the-fly (no storage). A deployment with PDF\ndisabled or missing WeasyPrint native libs returns a typed 501.",
        "operationId": "get_account_invoice_pdf",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Account Invoice Pdf",
        "tags": [
          "account_billing"
        ]
      }
    },
    "/v1/api_keys": {
      "get": {
        "description": "List your API keys, newest first.\n\nOnly keys in the same mode as the calling key are listed, so a test key\nnever sees live keys. Revoked keys are included, so check ``revoked_at``.\nThe keys themselves are never returned, only their prefixes.",
        "operationId": "list_api_keys",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_ApiKeyResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Api Keys",
        "tags": [
          "api_keys"
        ]
      },
      "post": {
        "description": "Issue a new API key.\n\nThe full key is returned once, in this response, and is never retrievable\nagain. Store it when you receive it. The new key is issued in the same\nmode as the key that created it, so a test key can only mint test keys.\n\n``scopes`` narrows what the key may do, which is the point of minting one\nper integration rather than sharing a single key. A key can never grant\nmore than it holds itself, so a narrowed key cannot mint a broader one,\nand an unrecognised scope string is rejected at creation rather than\nfailing later on every call. Omit ``scopes`` and the new key inherits the\ncalling key's own.",
        "operationId": "create_api_key",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Api Key",
        "tags": [
          "api_keys"
        ]
      }
    },
    "/v1/api_keys/{api_key_id}": {
      "get": {
        "description": "Retrieve one API key's metadata.\n\nThe key itself is never returned; only its prefix, label, scopes and\nwhether it has been revoked. ``last_used_at`` is the useful field here,\nsince it tells you whether a key is still in service before you revoke\nit. A key belonging to another account returns 404, not 403.",
        "operationId": "get_api_key",
        "parameters": [
          {
            "in": "path",
            "name": "api_key_id",
            "required": true,
            "schema": {
              "title": "Api Key Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Api Key",
        "tags": [
          "api_keys"
        ]
      }
    },
    "/v1/api_keys/{api_key_id}/revoke": {
      "post": {
        "description": "Revoke an API key so it stops working.\n\nDo this the moment a key might have leaked. It takes effect immediately\nand cannot be undone; issue a new key instead. Revoking an\nalready-revoked key returns it unchanged, so a retry is safe.\n\nA key is allowed to revoke itself, which is what you want if the leaked\nkey is the one you are calling with. Check ``last_used_at`` first if you\nare not sure what still depends on it.",
        "operationId": "revoke_api_key",
        "parameters": [
          {
            "in": "path",
            "name": "api_key_id",
            "required": true,
            "schema": {
              "title": "Api Key Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Revoke Api Key",
        "tags": [
          "api_keys"
        ]
      }
    },
    "/v1/audit_logs": {
      "get": {
        "description": "List the record of who changed what in your account, newest first.\n\nEvery change made through the API or the console writes a row here,\nincluding which key or person made it and from what address. Reach for it\nwhen you need to answer \"who cancelled this subscription\" or to satisfy\nan auditor.\n\nNarrow with ``action`` (for example ``subscription.canceled``),\n``resource_type``, ``resource_id`` or ``actor_id``. All four match\nexactly. Audit rows are written once and cannot be edited or removed.",
        "operationId": "list_audit_logs",
        "parameters": [
          {
            "in": "query",
            "name": "action",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Action"
            }
          },
          {
            "in": "query",
            "name": "resource_type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 32,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Resource Type"
            }
          },
          {
            "in": "query",
            "name": "resource_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Resource Id"
            }
          },
          {
            "in": "query",
            "name": "actor_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Actor Id"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_AuditLogResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Audit Logs",
        "tags": [
          "audit_logs"
        ]
      }
    },
    "/v1/audit_logs/{audit_log_id}": {
      "get": {
        "description": "Retrieve one audit entry, including the details recorded with it.\n\nAn entry belonging to another account returns 404, not 403.",
        "operationId": "get_audit_log",
        "parameters": [
          {
            "in": "path",
            "name": "audit_log_id",
            "required": true,
            "schema": {
              "title": "Audit Log Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Audit Log",
        "tags": [
          "audit_logs"
        ]
      }
    },
    "/v1/billing_portal/credit_notes": {
      "get": {
        "description": "The credit notes issued against this subscription's invoices.",
        "operationId": "portal_list_credit_notes",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 12,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalCreditNotePage"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Credit Notes",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/credit_notes/{credit_note_id}/pdf": {
      "get": {
        "description": "Serve the credit note PDF for a portal-authenticated customer.\n\nSubscription-scoped through the credited invoice, exactly as the list\nabove is. Blob storage streams the bytes inline; S3 storage 302s to a\npresigned URL. A deployment with rendering switched off answers a typed\n501 so the portal can show its disabled affordance rather than saving an\nerror page as a ``.pdf``.",
        "operationId": "portal_get_credit_note_pdf",
        "parameters": [
          {
            "in": "path",
            "name": "credit_note_id",
            "required": true,
            "schema": {
              "title": "Credit Note Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Credit Note Pdf",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/customer": {
      "post": {
        "operationId": "update_portal_customer_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PortalCustomerUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalSubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Portal Customer Route",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/invoices": {
      "get": {
        "operationId": "portal_list_invoices",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 12,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalInvoicePage"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Invoices",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/invoices/{invoice_id}/pdf": {
      "get": {
        "description": "Serve the invoice PDF for a portal-authenticated customer.\n\nSubscription-scoped \u2014 a portal token can only fetch PDFs for its\nown subscription's invoices. Blob storage streams bytes inline;\nS3 storage 302s to a presigned URL. Disabled deployments surface a\ntyped 501 so the portal UI can render its \"PDF coming soon\"\naffordance.",
        "operationId": "portal_get_invoice_pdf",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Invoice Pdf",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/payments": {
      "get": {
        "operationId": "portal_list_payments",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalPaymentsResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Payments",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/plans": {
      "get": {
        "operationId": "list_plans",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalPlansResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Plans",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/sessions": {
      "post": {
        "description": "Mint a link that lets a customer manage their own subscription.\n\nThe portal is where a customer updates their payment method, changes plan\nor cancels, without you building any of it. Create a session and send\nthem the ``url``. There is no customer login, so the link itself is the\ncredential: mint it on demand from a page where you already know who they\nare, and never put it anywhere it could be shared.\n\nA session covers exactly one subscription, so a customer with two needs\ntwo links. The token is returned once and cannot be recovered; mint a new\nsession instead. Links expire within a couple of hours and sooner if left\nidle. Set ``deliver_email`` to true to have us email the link to the\naddress on the customer record instead, which is skipped silently if they\nhave no address on file.",
        "operationId": "create_portal_session",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BillingPortalSessionCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BillingPortalSessionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Portal Session",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/sessions/{session_id}/revoke": {
      "post": {
        "description": "Invalidate a portal link that is already out in the world.\n\nUse it when a link has gone somewhere it should not have: forwarded to\nthe wrong person, pasted into a ticket, or reported by a customer as\nphishing. It takes effect immediately and cannot be undone; mint a fresh\nsession if the customer still needs access.\n\nRevoking an already-revoked session returns 200 and changes nothing, so a\nretry is safe. A session belonging to another account returns 404, not\n403.",
        "operationId": "revoke_portal_session",
        "parameters": [
          {
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BillingPortalSessionRevokeResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Revoke Portal Session",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/subscription": {
      "get": {
        "operationId": "portal_get_subscription",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalSubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Subscription",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/subscription/activate_import": {
      "post": {
        "description": "Mint the ``sequenceType=first`` verification payment that captures\na Mollie mandate for a subscription imported mandate-less from Stripe,\nand return its checkout URL.\n\nDistinct from :func:`reauthorize_pm`: the imported row has no Mollie\ncustomer *and* no Mollie subscription, so the completing webhook\n(``mollie_webhook/handlers/import_activation.py``) provisions the\nrecurring subscription in addition to attaching the mandate. Same\n``with_idempotency`` wrapper so the local Payment / operation / audit\nrows commit atomically with the returned URL.",
        "operationId": "activate_import",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PortalReauthorizeBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalRedirectResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Activate Import",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/subscription/apply_coupon": {
      "post": {
        "operationId": "apply_coupon",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PortalApplyCouponBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalApplyCouponResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Apply Coupon",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/subscription/cancel": {
      "post": {
        "operationId": "cancel",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalSubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Cancel",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/subscription/preview_update": {
      "post": {
        "operationId": "preview_update",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PortalPreviewBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalProrationPreview"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Preview Update",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/subscription/reactivate": {
      "post": {
        "description": "Undo a cancel-at-period-end before the period actually ends.\n\nDistinct route from ``/subscription/update`` (plan changes) and\n``/subscription/resume`` (unpause) so the portal frontend has one\nobvious call per intent and the audit log can tell the three\nflows apart. Mechanically identical to ``resume`` under the hood;\nthe service emits ``SUBSCRIPTION_REACTIVATED`` instead of\n``SUBSCRIPTION_RESUMED``.",
        "operationId": "reactivate",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalSubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Reactivate",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/subscription/reauthorize_payment_method": {
      "post": {
        "description": "Mint a verification Mollie payment + return its checkout URL.\n\nWrapped in :func:`with_idempotency` so the local Payment / audit /\nbilling-operation rows the service writes (``services/subscriptions/\nreauthorization.py``) commit atomically with the response. Without\nthe wrapper the customer would receive the checkout URL while the\nlocal state silently rolled back at session close.",
        "operationId": "reauthorize_pm",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PortalReauthorizeBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalRedirectResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Reauthorize Pm",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/subscription/resume": {
      "post": {
        "operationId": "resume",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalSubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Resume",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/billing_portal/subscription/update": {
      "post": {
        "description": "Plan change. Reactivate is its own route \u2014 see\n:func:`reactivate_subscription`.",
        "operationId": "update_plan",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PortalPlanChangeBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PortalSubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Plan",
        "tags": [
          "billing_portal"
        ]
      }
    },
    "/v1/checkout/one_shot": {
      "post": {
        "description": "Charge a customer once, with no subscription and no stored mandate.\n\nThis is the endpoint for a one-off sale: a top-up, a setup fee, a single\norder. Send the customer to the ``redirect_url`` in the response to pay.\nNothing recurs, and no payment method is kept for later, so a second\ncharge means a second call and another trip through checkout.\n\nThe payment is not settled when this returns. It starts ``open`` and only\nbecomes ``paid`` once the provider confirms, which arrives as a\n``one_shot_payment.succeeded`` webhook. The customer must already exist, and\n``method`` must be one your account and the customer's country both\nsupport. ``tax_behavior`` decides whether ``amount_cents`` includes tax or\nhas it added on top.",
        "operationId": "create_one_shot",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OneShotPaymentCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OneShotPaymentResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create One Shot",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/checkout/one_shot/{one_shot_id}": {
      "get": {
        "description": "Retrieve one one-off payment, including how much of it has been refunded.\n\n``amount_refunded_cents`` and ``amount_refundable_cents`` tell you what is\nleft to give back, which is what you need before calling\n``POST /v1/refunds``. Note that ``amount_refundable_cents`` ignores the\nrefund window, so a fully refundable balance can still be refused if the\nwindow has closed.\n\nA partial refund leaves the status ``paid`` with a balance remaining; only\na full refund flips it to ``refunded``. A payment belonging to another\naccount returns 404, not 403.",
        "operationId": "get_one_shot",
        "parameters": [
          {
            "in": "path",
            "name": "one_shot_id",
            "required": true,
            "schema": {
              "title": "One Shot Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OneShotPaymentResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get One Shot",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/checkout/payment-methods": {
      "get": {
        "description": "The customer's saved payment methods for the ``<PaymentMethodElement/>``.\n\nAuthenticated by the ephemeral ``client_secret`` (API keys rejected).\nThe customer is derived from the token's checkout session \u2014 never from a\nclient-supplied id \u2014 so the iframe can only read its own customer's\nmethods.",
        "operationId": "list_checkout_payment_methods",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutPaymentMethodsResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Checkout Payment Methods",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/checkout/payment-methods/setup": {
      "post": {
        "description": "Mint a wallet \"Add a payment method\" setup (SetupIntent shape).",
        "operationId": "create_payment_method_setup",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutSetupResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Create Payment Method Setup",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/checkout/payment-methods/setup/confirm": {
      "post": {
        "description": "Confirm the setup \u2014 charge the verification payment that mints a mandate.",
        "operationId": "confirm_payment_method_setup",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutSetupConfirmRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutSetupConfirmResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Confirm Payment Method Setup",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/checkout/payment-methods/{mandate_id}/default": {
      "post": {
        "description": "Set the customer's default saved method to ``mandate_id``.",
        "operationId": "set_default_payment_method",
        "parameters": [
          {
            "in": "path",
            "name": "mandate_id",
            "required": true,
            "schema": {
              "title": "Mandate Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutPaymentMethodsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Set Default Payment Method",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/checkout/payment-methods/{mandate_id}/remove": {
      "post": {
        "description": "Revoke + soft-delete the saved method ``mandate_id``.",
        "operationId": "remove_payment_method",
        "parameters": [
          {
            "in": "path",
            "name": "mandate_id",
            "required": true,
            "schema": {
              "title": "Mandate Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutPaymentMethodsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Remove Payment Method",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/checkout/sessions": {
      "post": {
        "description": "Start a subscription sign-up.\n\nThis is the only way to create a subscription; there is no\n``POST /v1/subscriptions``. Create a session for a price, send the\ncustomer to the ``url`` in the response, and the subscription is created\nfor you once they pay. Nothing exists under ``GET /v1/subscriptions``\nuntil then.\n\nIdentify the customer with ``customer_id``, or with ``customer_email`` to\nhave one created. The email path creates a new customer every time, never\nmatches an existing one by address, and the customer is kept even if the\npayment then fails.\n\nSet ``ui_mode`` to ``embedded`` to collect payment inside your own page:\nthat returns a ``client_secret`` for the checkout element and leaves\n``url`` null, because no charge is made until the element confirms. A\ncustomer can only have one sign-up in progress at a time, so a second one\nreturns 409 until the first resolves.\n\nSend ``country`` if you know where the buyer is. VAT is decided from the\ncustomer's country before the charge is created, so on the hosted flow\nthis is the only way the first payment can carry tax: the buyer does not\nreach a page that asks them until after the charge exists. The embedded\nelement asks the buyer itself and needs nothing from you. Either way the\nvalue only fills a blank: a country already on the customer is kept.",
        "operationId": "create_checkout_session",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutSessionCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutSessionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Checkout Session",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/checkout/sessions/{checkout_id}": {
      "get": {
        "description": "Retrieve one checkout session, to see whether the customer completed it.\n\nUseful on your success page, where the customer lands before the payment\nprovider has necessarily told us the payment settled. A ``complete``\nstatus means the sign-up went through; ``open`` means it has not resolved\nyet. Webhooks are the reliable signal, so treat polling here as a way to\nrender the right thing immediately, not as your source of truth.\n\nA session belonging to another account returns 404, not 403.",
        "operationId": "get_checkout_session",
        "parameters": [
          {
            "in": "path",
            "name": "checkout_id",
            "required": true,
            "schema": {
              "title": "Checkout Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutSessionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Checkout Session",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/checkout/sessions/{checkout_id}/confirm": {
      "post": {
        "operationId": "confirm_checkout_session",
        "parameters": [
          {
            "in": "path",
            "name": "checkout_id",
            "required": true,
            "schema": {
              "title": "Checkout Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutConfirmRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutConfirmResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Confirm Checkout Session",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/checkout/sessions/{checkout_id}/coupon": {
      "post": {
        "description": "Apply or clear a promotion code the buyer typed into the element.\n\nReturns the **refreshed element view**, not a bespoke quote object, so\nthe amount the buyer now sees is produced by exactly the code path that\nrenders the element and exactly the one ``/confirm`` charges from.\nThere is no third place for the number to drift.\n\nNothing is redeemed here. The coupon's redemption slot is claimed when\nthe payment settles, so a buyer can try a code, see the new price and\nwalk away without consuming a single-use code.\n\nRefused with ``parameter_invalid`` when the product has not opted in\nvia ``allow_promotion_codes``, when the checkout is no longer open, or\nwhen the code is unknown / expired / exhausted / not applicable \u2014 the\n``reason`` field carries which, for the element's inline copy.",
        "operationId": "apply_checkout_coupon",
        "parameters": [
          {
            "in": "path",
            "name": "checkout_id",
            "required": true,
            "schema": {
              "title": "Checkout Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutCouponRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutElementResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Apply Checkout Coupon",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/checkout/sessions/{checkout_id}/element": {
      "get": {
        "operationId": "get_checkout_element",
        "parameters": [
          {
            "in": "path",
            "name": "checkout_id",
            "required": true,
            "schema": {
              "title": "Checkout Id",
              "type": "string"
            }
          },
          {
            "description": "ISO-3166-1 alpha-2 country of the buyer, forwarded by the element's country select. Used only to hide national bank-redirect methods (iDEAL/Bancontact/EPS) a buyer there cannot complete, and only when the customer carries no stored country_code. Unverified and unparseable values are ignored rather than rejected \u2014 an unknown country shows every method the tenant enabled.",
            "in": "query",
            "name": "country",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "ISO-3166-1 alpha-2 country of the buyer, forwarded by the element's country select. Used only to hide national bank-redirect methods (iDEAL/Bancontact/EPS) a buyer there cannot complete, and only when the customer carries no stored country_code. Unverified and unparseable values are ignored rather than rejected \u2014 an unknown country shows every method the tenant enabled.",
              "title": "Country"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutElementResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Checkout Element",
        "tags": [
          "checkout"
        ]
      }
    },
    "/v1/console/auth/factors": {
      "get": {
        "description": "What the console Security tab renders its toggles from.",
        "operationId": "factors_route",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_FactorsResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Factors Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/login": {
      "post": {
        "description": "Public: authenticate with email + password.\n\nReturns either a session or an MFA challenge \u2014 see\n:mod:`services.operator_login` for which, and why a magic link is\nheld to the same rule.",
        "operationId": "login_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_LoginBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "discriminator": {
                    "mapping": {
                      "operator.mfa_challenge": "#/components/schemas/MfaChallengeResult",
                      "operator.session": "#/components/schemas/SessionResult"
                    },
                    "propertyName": "object"
                  },
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/SessionResult"
                    },
                    {
                      "$ref": "#/components/schemas/MfaChallengeResult"
                    }
                  ],
                  "title": "Response Login Route"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Login Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/logout": {
      "post": {
        "description": "Revoke the calling session.\n\nIdempotent \u2014 a revoked session's revoke is a no-op that still\nreturns 200 so a naive client (or a retried logout) does not\nsee a spurious failure.\n\nUses the session row already resolved by the auth dep \u2014 no\nre-query.",
        "operationId": "logout_route",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_StatusResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Logout Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/me": {
      "get": {
        "description": "Return the authenticated operator's identity + session state.\n\nUses the operator + session rows already resolved by the auth\ndep \u2014 no re-query. A vanished operator or session can never\nreach this route: :func:`resolve_operator_principal` would have\nraised 401 first.",
        "operationId": "me_route",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_MeResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Me Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/mfa/verify": {
      "post": {
        "description": "Public: redeem an MFA challenge with a TOTP or recovery code.\n\nAccepts either factor on the same endpoint: a locked-out operator\nreaching for a recovery code is already having a bad time, and making\nthem find a different form is friction with no security value. The\ncode shape disambiguates.\n\nA wrong code does **not** burn the challenge immediately \u2014 a single\ntypo would otherwise throw the operator back to the password screen.\nBut \"does not burn\" must not mean \"unlimited guesses for the full\nTTL\": a 6-digit code with \u00b11 step of drift leaves 3 of 10^6 values\nlive at any instant, and the attacker this factor exists to stop\nalready has the password and can spread guesses across hosts, so the\nper-IP limiter alone is not a bound.\n\nSo guesses are capped twice: ``MAX_MFA_ATTEMPTS`` per challenge (on\nthe row, so the cap survives across API replicas), and a per-operator\nbudget shared with the step-up routes. Exhausting either answers with\nthe same generic failure as a wrong code \u2014 telling an attacker they\nhit a limit would confirm the account is real.",
        "operationId": "mfa_verify_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_MfaVerifyBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "discriminator": {
                    "mapping": {
                      "operator.mfa_challenge": "#/components/schemas/MfaChallengeResult",
                      "operator.session": "#/components/schemas/SessionResult"
                    },
                    "propertyName": "object"
                  },
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/SessionResult"
                    },
                    {
                      "$ref": "#/components/schemas/MfaChallengeResult"
                    }
                  ],
                  "title": "Response Mfa Verify Route"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Mfa Verify Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/notify_owner": {
      "post": {
        "description": "Session-authed: nudge the tenant owner to grant the caller a role.\n\nAlways returns 200 ``{\"status\":\"ok\"}`` regardless of whether the\nemail actually went out. The design UX (\"Ask your workspace owner\"\non the Access Denied screen) doesn't need to distinguish \"sent\"\nfrom \"throttled\" from \"you are the owner\" \u2014 differentiating would\nlet a hostile teammate probe the roster.\n\nStructured log captures ``NotifyOwnerOutcome`` so ops can watch\nfor spam patterns without leaking the shape back to the caller.",
        "operationId": "notify_owner_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_NotifyOwnerBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_StatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Notify Owner Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/passkeys": {
      "get": {
        "operationId": "list_passkeys_route",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_PasskeyListResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Passkeys Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/passkeys/authenticate/options": {
      "post": {
        "description": "Public: start a passkey sign-in.\n\nAn unknown email returns a perfectly normal challenge with no\n``allowCredentials``. That is deliberate: 404-ing here, or returning\nan empty credential list only for unknown addresses, would turn this\ninto an account-enumeration oracle. The assertion simply fails later.",
        "operationId": "passkey_auth_options_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_PasskeyAuthOptionsBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_PasskeyAuthOptionsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Passkey Auth Options Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/passkeys/authenticate/verify": {
      "post": {
        "description": "Public: finish a passkey sign-in and mint a session.\n\nNo second factor is demanded \u2014 a user-verified, origin-bound\nassertion is already stronger than password + TOTP. See\n:mod:`services.operator_login`.",
        "operationId": "passkey_auth_verify_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_PasskeyAuthVerifyBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "discriminator": {
                    "mapping": {
                      "operator.mfa_challenge": "#/components/schemas/MfaChallengeResult",
                      "operator.session": "#/components/schemas/SessionResult"
                    },
                    "propertyName": "object"
                  },
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/SessionResult"
                    },
                    {
                      "$ref": "#/components/schemas/MfaChallengeResult"
                    }
                  ],
                  "title": "Response Passkey Auth Verify Route"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Passkey Auth Verify Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/passkeys/register/options": {
      "post": {
        "description": "Start passkey registration for the calling operator. Requires a step-up.\n\nThis is the gate for the whole ceremony, and it is as\nsecurity-relevant as ``totp_disable_route``. A passkey is durable \u2014\nit survives every session revocation and every password change \u2014 and\na passkey login deliberately mints a session with no second factor\n(see :mod:`services.operator_login`). So a stolen session that could\nenroll an attacker's authenticator would convert a few hours of\naccess into permanent, MFA-free access to the account, and nothing\nthe real operator does afterwards short of noticing the extra\ncredential would evict it.\n\nThe step-up lives here rather than on ``/verify`` for two reasons.\nIt fails the operator *before* they are asked to touch their\nauthenticator, and \u2014 the load-bearing one \u2014 a TOTP code is strictly\nsingle-use (``operator_totp`` records a counter high-water mark), so\na check on both halves of the ceremony could not be satisfied by one\ncode. ``/verify`` is gated transitively instead: it only accepts a\n``webauthn_register`` challenge bound to the calling operator, and\nthis route is the only thing that mints one.",
        "operationId": "passkey_register_options_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/_PasskeyRegisterOptionsBody"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Body"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_PasskeyRegisterOptionsResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Passkey Register Options Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/passkeys/register/verify": {
      "post": {
        "description": "Finish passkey registration. Step-up gated via the challenge.\n\nThe two checks below are the second half of the step-up on\n:func:`passkey_register_options_route`, not merely a sanity check.\nA ``webauthn_register`` challenge is server-minted, single-use,\nexpires in minutes, and is handed back only to the caller that\npassed the step-up \u2014 so possessing one, bound to this operator, is\nproof that the step-up happened. Nothing else in the codebase issues\nthat purpose.",
        "operationId": "passkey_register_verify_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_PasskeyRegisterVerifyBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_PasskeyView"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Passkey Register Verify Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/passkeys/{passkey_id}": {
      "delete": {
        "description": "Revoke one passkey. Ownership-scoped \u2014 see the service.",
        "operationId": "delete_passkey_route",
        "parameters": [
          {
            "in": "path",
            "name": "passkey_id",
            "required": true,
            "schema": {
              "title": "Passkey Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_StatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Passkey Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/password": {
      "post": {
        "description": "Set or change the calling operator's password. Requires a step-up.\n\nChanging an existing password requires the current one. A session\nalone is not enough: sessions live for hours and can be stolen, and a\nsilent password change is how an attacker converts temporary access\ninto permanent access while locking the owner out.\n\nThe *first* set is the same problem wearing a different hat. An\noperator who signs in with a passkey or a magic link plus TOTP has no\npassword, so ``current_password`` has nothing to check \u2014 and the\nroute used to accept a bare ``new_password`` on a session alone,\nhanding a session thief a durable credential on an account that had\ndeliberately never had one. So when the operator holds any other\nfactor, that factor is what authorises the first set. A brand-new\noperator with nothing enrolled is exempt (see the module docstring);\nfor them this route *is* the bootstrap.\n\nEvery *other* session is revoked on success \u2014 the standard\n\"changed my password because something felt wrong\" expectation, and\nthe only thing that actually evicts an attacker who already has one.",
        "operationId": "set_password_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_SetPasswordBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_StatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Set Password Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/request_login_link": {
      "post": {
        "description": "Public: request a magic link for the given email.\n\nAlways returns ``{\"status\":\"ok\"}`` regardless of whether an\noperator exists with that email. The email-existence probe\nprotection is the whole point of this route \u2014 do NOT surface\n\"not found\" back to the caller.\n\nTwo rate-limit layers:\n\n* :func:`enforce_auth_rate_limit` \u2014 per-client-IP bucket, same\n  as API-key auth. Blunts brute-force enumeration from a single\n  IP. Deliberately not refunded on success (a real operator's\n  request still costs a bucket token so timing/budget signals\n  don't leak \"this email exists\").\n* :func:`services.operator_auth._should_mint_login_link_for` \u2014\n  per-normalized-email bucket in the service. Caps total mints\n  per email per hour regardless of source IP, so an attacker\n  rotating IPs cannot spam a targeted operator's inbox. The\n  throttle is silent \u2014 a saturated bucket returns the same 200\n  shape as an unknown email.\n\nDelivery is queued on the outbox, not sent here. The reason the\nsend used to run in a :class:`BackgroundTasks` task was to decouple\nresponse time from it, so the \"known email\" and \"unknown email\"\nbranches finish at about the same wall-clock instant and the route\nis not a timing oracle for enumeration. **That property is\npreserved and must stay preserved**: what left the request path was\na provider POST with a ten-second timeout, and what replaced it is a\nsub-millisecond INSERT inside a transaction that already writes a\nrow conditionally on the address existing. The oracle's magnitude\ndropped by four orders of magnitude and its class did not change.\nDo not add a conditional query here.\n\nWhat the BackgroundTask could not do is survive. It ran after the\nresponse, in the API process, on a multi-replica deployment: a\nrolling restart between response and send dropped the link, and the\noperator saw \"check your email\" and got nothing.",
        "operationId": "request_login_link_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_RequestLoginLinkBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_StatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Request Login Link Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/sessions": {
      "get": {
        "description": "List the calling operator's live sessions.\n\nPowers the console Security tab's \"Active sessions\" card. Scoped to\nthe caller's own ``operator_id`` \u2014 an operator never sees another\noperator's sessions, even within the same tenant. Only live sessions\nare returned (see :func:`list_operator_sessions`); revoked / expired\nrows are omitted so the list reflects what's genuinely signed in.",
        "operationId": "list_sessions_route",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_SessionListResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Sessions Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/sessions/revoke_others": {
      "post": {
        "description": "Sign out every other session, keeping the caller's own.\n\nThe \"Revoke all others\" action. Returns the count actually revoked\nso the console can report \"signed out N other sessions\".",
        "operationId": "revoke_other_sessions_route",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_RevokeOthersResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Revoke Other Sessions Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/sessions/{session_id}/revoke": {
      "post": {
        "description": "Revoke one of the caller's own sessions by id.\n\nThe per-row \"Revoke\" action. Ownership-scoped: a bad or someone\nelse's ``session_id`` returns a generic 404 rather than confirming\nthe id exists. Idempotent. Revoking the *current* session is allowed\n(it's equivalent to logout) \u2014 the console only surfaces the button\non other sessions, but the endpoint doesn't special-case it.",
        "operationId": "revoke_session_route",
        "parameters": [
          {
            "in": "path",
            "name": "session_id",
            "required": true,
            "schema": {
              "title": "Session Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_StatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Revoke Session Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/sign_up": {
      "post": {
        "description": "Public: self-serve tenant creation.\n\nProvisions tenant + owner operator + Mollie webhook route + optional\nportal branding, all atomically.\n\nDeliberately takes **no** Mollie credential. Sign-up used to offer a\nthree-way choice \u2014 authorise via Connect, paste an API key, or decide\nlater \u2014 and two of the three did nothing: both left the tenant without\na credential and pointed them at Settings anyway. The third asked a\nfounder to paste an organisation-wide, non-expiring Mollie secret into\na third party on their first screen, where OAuth gives a scoped token\nthat expires in an hour, refreshes, and is revocable from Mollie's\nside. Connecting happens in Settings \u2192 Mollie, and the wizard says so\nrather than asking. Mints a login magic link for the owner and\nqueues it on the outbox in the same transaction that provisions the\ntenant, so a brand-new workspace can never exist with its owner\nholding no way into it.\n\nAbuse controls: client-IP token bucket\n(:func:`enforce_auth_rate_limit`) + per-email daily cap\n(:mod:`services.tenant_signup`). Both fire uniform 429s; any\nvalidation problem returns 400 with a specific ``code`` so the\nfrontend can highlight the offending field.",
        "operationId": "sign_up_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_SignUpBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_SignUpResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Sign Up Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/totp/confirm": {
      "post": {
        "description": "Prove possession of the authenticator and arm TOTP.",
        "operationId": "totp_confirm_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_TotpConfirmBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_RecoveryCodesResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Totp Confirm Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/totp/disable": {
      "post": {
        "description": "Turn off TOTP. Requires a step-up.\n\n``POST`` rather than ``DELETE`` because the step-up code travels in\nthe body, and a DELETE with a body is legal-but-poorly-supported \u2014\nproxies and HTTP clients drop it often enough that the security check\nwould silently become optional.\n\nDemanding a current factor \u2014 not just the session \u2014 is the whole\npoint: otherwise a stolen session could strip the second factor and\nconvert itself into durable access. This is the single most\nsecurity-relevant check in the module.",
        "operationId": "totp_disable_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_TotpDisableBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_StatusResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Totp Disable Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/totp/enroll": {
      "post": {
        "description": "Begin TOTP enrollment. Does not arm the factor.\n\nThe secret only starts gating login once\n:func:`totp_confirm_route` sees a live code \u2014 an abandoned\nenrollment must never lock anyone out.",
        "operationId": "totp_enroll_route",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_TotpEnrollResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Totp Enroll Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/totp/recovery_codes": {
      "post": {
        "description": "Re-issue recovery codes, invalidating the previous batch.\n\nStep-up gated for the same reason as disabling: a fresh batch makes\nthe operator's printed sheet useless, which is exactly what an\nattacker holding a session would want to do.",
        "operationId": "regenerate_recovery_codes_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_TotpConfirmBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_RecoveryCodesResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Regenerate Recovery Codes Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/auth/verify": {
      "post": {
        "description": "Public: consume a magic-link token and mint a session.\n\nErrors uniformly as a generic 401 \u2014 never surface the\ndistinction between \"unknown\", \"expired\", \"already consumed\",\nor \"operator disabled\" (attackers use those signals to\nfingerprint valid-but-consumed tokens).",
        "operationId": "verify_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_VerifyBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "discriminator": {
                    "mapping": {
                      "operator.mfa_challenge": "#/components/schemas/MfaChallengeResult",
                      "operator.session": "#/components/schemas/SessionResult"
                    },
                    "propertyName": "object"
                  },
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/SessionResult"
                    },
                    {
                      "$ref": "#/components/schemas/MfaChallengeResult"
                    }
                  ],
                  "title": "Response Verify Route"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Verify Route",
        "tags": [
          "console_auth"
        ]
      }
    },
    "/v1/console/import/stripe/connect": {
      "post": {
        "description": "Validate the pasted key and mint a short-lived scan session.",
        "operationId": "connect_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_ConnectBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_ConnectResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Connect Route",
        "tags": [
          "console_import"
        ]
      }
    },
    "/v1/console/import/stripe/customers": {
      "get": {
        "description": "Page the connected Stripe account for the selection table.",
        "operationId": "customers_route",
        "parameters": [
          {
            "in": "query",
            "name": "scan_token",
            "required": true,
            "schema": {
              "maxLength": 128,
              "minLength": 8,
              "title": "Scan Token",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "cursor",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Cursor"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_CustomersResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Customers Route",
        "tags": [
          "console_import"
        ]
      }
    },
    "/v1/console/import/stripe/dry_run": {
      "post": {
        "description": "Map Stripe \u2192 BillKit and report counts + caveats. Writes nothing.",
        "operationId": "dry_run_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_SelectionBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_DryRunResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Dry Run Route",
        "tags": [
          "console_import"
        ]
      }
    },
    "/v1/console/import/stripe/jobs/{job_id}": {
      "get": {
        "description": "Point-in-time snapshot of an import job (polling fallback).",
        "operationId": "job_route",
        "parameters": [
          {
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "title": "Job Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_JobResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Job Route",
        "tags": [
          "console_import"
        ]
      }
    },
    "/v1/console/import/stripe/jobs/{job_id}/events": {
      "get": {
        "description": "Server-Sent Events stream of the import progress log.\n\nTails :attr:`StripeImportJob.events_json`, emitting each new line as\nit lands and a final ``event: done`` when the job reaches a terminal\nstate. Reads the job in a fresh short-lived session per poll so no DB\nsession is held across the sleep \u2014 the background writer commits\nincrementally, so each poll sees fresh progress.",
        "operationId": "job_events_route",
        "parameters": [
          {
            "in": "path",
            "name": "job_id",
            "required": true,
            "schema": {
              "title": "Job Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Job Events Route",
        "tags": [
          "console_import"
        ]
      }
    },
    "/v1/console/import/stripe/run": {
      "post": {
        "description": "Create the import job and queue it for a worker.\n\nRow and work order are written in one transaction. The previous\nshape committed the row and then fired an ``asyncio.create_task``\non this replica, so a restart in between left an import at\n``status='running'`` that nothing was executing and nothing would\nresume.",
        "operationId": "run_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_SelectionBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "202": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_JobResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Run Route",
        "tags": [
          "console_import"
        ]
      }
    },
    "/v1/console/onboarding/mollie/authorize": {
      "get": {
        "description": "Return the Mollie consent URL for the caller's tenant.\n\n501s cleanly when the deployment has no Mollie OAuth app configured\n(``oauth.build_authorize_url`` raises), so the SPA can fall back to the\npaste-a-key flow.",
        "operationId": "authorize_route",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_AuthorizeResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Authorize Route",
        "tags": [
          "console_onboarding"
        ]
      }
    },
    "/v1/console/team": {
      "get": {
        "description": "The team roster: members, pending invites, and seat usage.",
        "operationId": "team_route",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_TeamResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Team Route",
        "tags": [
          "console_team"
        ]
      }
    },
    "/v1/console/team/invites": {
      "post": {
        "description": "Invite a teammate, and email them the accept link.\n\nRefuses on an existing member, a still-pending invite for the same\naddress, or an exhausted seat limit \u2014 see\n:func:`services.team.assert_can_invite` for the ordering and why.",
        "operationId": "invite_route",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/_InviteBody"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_TeamResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Invite Route",
        "tags": [
          "console_team"
        ]
      }
    },
    "/v1/console/team/invites/{invite_id}/revoke": {
      "post": {
        "description": "Kill a pending invite's link.\n\n404s on an invite that is already consumed, expired, or belongs to\nanother tenant \u2014 all three are \"there is nothing here to revoke\",\nand distinguishing them would leak whether an id exists elsewhere.",
        "operationId": "revoke_invite_route",
        "parameters": [
          {
            "in": "path",
            "name": "invite_id",
            "required": true,
            "schema": {
              "title": "Invite Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_TeamResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Revoke Invite Route",
        "tags": [
          "console_team"
        ]
      }
    },
    "/v1/console/team/members/{operator_id}/disable": {
      "post": {
        "description": "Revoke a teammate's access and end their live sessions.",
        "operationId": "disable_member_route",
        "parameters": [
          {
            "in": "path",
            "name": "operator_id",
            "required": true,
            "schema": {
              "title": "Operator Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_TeamResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Disable Member Route",
        "tags": [
          "console_team"
        ]
      }
    },
    "/v1/console/team/members/{operator_id}/enable": {
      "post": {
        "description": "Restore a previously-removed teammate, seat limit permitting.",
        "operationId": "enable_member_route",
        "parameters": [
          {
            "in": "path",
            "name": "operator_id",
            "required": true,
            "schema": {
              "title": "Operator Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/_TeamResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Enable Member Route",
        "tags": [
          "console_team"
        ]
      }
    },
    "/v1/coupons": {
      "get": {
        "description": "List coupons, newest first.\n\nWithdrawn coupons are included, so check ``active`` before showing a\ncode as available.",
        "operationId": "list_coupons",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_CouponResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Coupons",
        "tags": [
          "coupons"
        ]
      },
      "post": {
        "description": "Create a discount code customers can enter at checkout.\n\nChoose a percentage or a fixed amount off, and how long it lasts: once,\nforever, or for a set number of months. You can limit it further with a\ntotal redemption cap, an expiry date, a minimum order amount, and a list\nof prices it applies to.\n\nCodes are normalised, so they are matched without regard to case or\nsurrounding whitespace, and two coupons cannot share one. A duplicate is\na 400. Pass the code to ``POST /v1/checkout/sessions`` to apply it.",
        "operationId": "create_coupon",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CouponCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CouponResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Coupon",
        "tags": [
          "coupons"
        ]
      }
    },
    "/v1/coupons/validate": {
      "post": {
        "description": "Check whether a code is usable, and what it would take off.\n\nCall this as the customer types a code, before they get as far as\ncheckout. It changes nothing and consumes no redemption, so it is safe to\ncall repeatedly.\n\nA code that is unknown, expired, exhausted or not applicable comes back\nas a 200 with ``valid: false`` and a ``reason``, not as an error, because\na mistyped coupon is ordinary input. Send ``amount_cents`` as well to get\nthe discount and the resulting charge back; without it you only learn\nwhether the code is usable.",
        "operationId": "validate_coupon",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CouponValidateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CouponValidateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Validate Coupon",
        "tags": [
          "coupons"
        ]
      }
    },
    "/v1/coupons/{coupon_id}": {
      "get": {
        "description": "Retrieve one coupon, including how many times it has been redeemed.\n\nWithdrawn coupons are still returned, with ``active: false``, so a\ndiscount on a live subscription can be traced back to the coupon that\ngranted it. A coupon belonging to another account returns 404, not 403.",
        "operationId": "get_coupon",
        "parameters": [
          {
            "in": "path",
            "name": "coupon_id",
            "required": true,
            "schema": {
              "title": "Coupon Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CouponResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Coupon",
        "tags": [
          "coupons"
        ]
      },
      "post": {
        "description": "Update a coupon's limits, or withdraw it.\n\nOnly the fields you send change. Sending ``active: false`` withdraws the\ncode: it stops being accepted at checkout, while the coupon stays\nreadable and discounts already applied to a subscription go on working\nout. That is how you retire a campaign, and it is the only way to\nwithdraw one, because a coupon that has been redeemed is part of what a\ncustomer was charged and has to stay answerable.\n\nSend ``active: true`` to bring a campaign back. The code itself and the\ndiscount cannot be changed here. That is deliberate: a coupon customers\nhave already redeemed has to keep meaning what it meant. Create a new\ncoupon instead.",
        "operationId": "update_coupon",
        "parameters": [
          {
            "in": "path",
            "name": "coupon_id",
            "required": true,
            "schema": {
              "title": "Coupon Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CouponUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CouponResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Coupon",
        "tags": [
          "coupons"
        ]
      }
    },
    "/v1/credit_notes": {
      "get": {
        "description": "List credit notes, newest first.\n\nFilter by ``invoice_id`` to answer \"was this sale credited, and by how\nmuch\", which is the question when reconciling a single invoice. Filter by\n``customer_id`` for everything credited back to one customer.",
        "operationId": "list_credit_notes",
        "parameters": [
          {
            "in": "query",
            "name": "invoice_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Invoice Id"
            }
          },
          {
            "in": "query",
            "name": "customer_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Customer Id"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_CreditNoteResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Credit Notes",
        "tags": [
          "credit_notes"
        ]
      }
    },
    "/v1/credit_notes/{credit_note_id}": {
      "get": {
        "description": "Retrieve one credit note.\n\nA credit note is the document that reverses part or all of an invoice.\nThey are issued for you when a refund settles, so there is no route to\nwrite one, and none is issued while a refund is still pending or if it\nfails. A refund of a one-off charge never produces a credit note, because\na one-off charge is not invoiced. A credit note belonging to another\naccount returns 404, not 403.",
        "operationId": "get_credit_note",
        "parameters": [
          {
            "in": "path",
            "name": "credit_note_id",
            "required": true,
            "schema": {
              "title": "Credit Note Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditNoteResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Credit Note",
        "tags": [
          "credit_notes"
        ]
      }
    },
    "/v1/credit_notes/{credit_note_id}/pdf": {
      "get": {
        "description": "Download the credit note as a PDF.\n\nThis is the document that evidences a refund for accounting purposes.\nAs with invoice PDFs, you will either receive the bytes directly or a\nredirect to a short-lived download link, so follow redirects. If PDF\nrendering is not available you get a 501 whose body carries the full\ncredit-note data so you can produce your own document.",
        "operationId": "get_credit_note_pdf",
        "parameters": [
          {
            "in": "path",
            "name": "credit_note_id",
            "required": true,
            "schema": {
              "title": "Credit Note Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Credit Note Pdf",
        "tags": [
          "credit_notes"
        ]
      }
    },
    "/v1/customers": {
      "get": {
        "description": "List your customers, newest first.\n\nDeleted and purged customers are left out. There is no email or name\nsearch here, so if you need to find a customer by something other than\ntheir id, keep your own mapping from your user to the BillKit customer id\nat the point you create them.\n\nA checkout that captures an email commits a Customer before the charge,\nso a checkout somebody abandoned leaves a row behind with\n``provisional: true``. This endpoint returns **both kinds by default**\n\u2014 narrowing it would silently change what existing integrations see \u2014\nso pass ``provisional=false`` for paying customers only. Those rows are\nswept after ``PROVISIONAL_CUSTOMER_RETENTION_DAYS``, so treat them as a\nrecovery window rather than a durable record.",
        "operationId": "list_customers",
        "parameters": [
          {
            "description": "Filter by whether the customer ever completed a payment. `false` returns real customers only; `true` returns abandoned checkouts (useful for cart-recovery email); omit to return both.",
            "in": "query",
            "name": "provisional",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by whether the customer ever completed a payment. `false` returns real customers only; `true` returns abandoned checkouts (useful for cart-recovery email); omit to return both.",
              "title": "Provisional"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          },
          {
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 256,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Expand"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_CustomerResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Customers",
        "tags": [
          "customers"
        ]
      },
      "post": {
        "description": "Create a customer, the record everything else in an account hangs off.\n\nCreate one before you need a subscription, a one-off charge or a portal\nlink for someone. You can also skip this and pass ``customer_email`` to\ncheckout, which creates the customer for you.\n\nNothing here is deduplicated. Two calls with the same email produce two\nseparate customers, so if you already have your own identifier for a\nperson, store the returned ``id`` against it rather than looking them up\nby email later. Send an ``Idempotency-Key`` header if a retry must not\ncreate a second row.",
        "operationId": "create_customer",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Customer",
        "tags": [
          "customers"
        ]
      }
    },
    "/v1/customers/{customer_id}": {
      "delete": {
        "description": "Delete a customer.\n\nThe customer is gone from the API: ``GET /v1/customers/{id}`` returns a\n404 and they no longer appear in listings. There is no way to bring\nthem back, so the response is a deletion marker rather than the\ncustomer, and it is the only thing you get back.\n\nTheir payments, invoices and refunds are untouched and still resolve,\nbecause you have to be able to account for money that moved. The\npersonal data is still there too, so this is not an erasure. Use\n``POST /v1/customers/{id}/purge`` for a GDPR erasure request.\n\nA customer who is still being charged but can no longer be seen is the\nworst of both, so this is refused while the customer has a subscription\nthat is active, trialing, past due or incomplete. A trial counts,\nbecause it turns into a real charge on its own once it ends. Cancel the\nsubscription first, then delete. Nothing is cancelled for you, because\na delete call should never end someone's service on its own.",
        "operationId": "delete_customer",
        "parameters": [
          {
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "title": "Customer Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Customer",
        "tags": [
          "customers"
        ]
      },
      "get": {
        "description": "Retrieve one customer.\n\nDeleted and purged customers are not returned, so a customer you removed\nreads as 404 from here onwards even though the row is still there backing\ntheir old invoices. A customer belonging to another account is also 404,\nnever 403.",
        "operationId": "get_customer",
        "parameters": [
          {
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "title": "Customer Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Customer",
        "tags": [
          "customers"
        ]
      },
      "post": {
        "description": "Update a customer's details.\n\nOnly the fields you send are changed; anything you leave out keeps its\ncurrent value. Sending ``metadata`` replaces the whole object rather than\nmerging into it, so read the current value first if you only mean to add\na key.\n\n``country_code`` decides which VAT rate applies to this customer's next\ncharge. Changing it never reprices anything already invoiced. Use\n``POST /v1/customers/{id}/vat_number`` for the VAT registration itself,\nwhich is validated and cannot be set here.",
        "operationId": "update_customer",
        "parameters": [
          {
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "title": "Customer Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Customer",
        "tags": [
          "customers"
        ]
      }
    },
    "/v1/customers/{customer_id}/purge": {
      "post": {
        "description": "Erase a customer's personal data while keeping their financial history.\n\nThis is the endpoint for a GDPR erasure request. The email is replaced\nwith an unusable placeholder, the name and metadata are cleared, and the\nrow is marked deleted. Their payments, refunds and invoices stay intact,\nbecause you still have to be able to account for money that moved.\n\nIt cannot be undone, so you must send ``confirmed: true`` to prove you\nmeant it. It is refused while the customer has a subscription that is\nactive, trialing, past due, paused or incomplete, or while a charge is\nstill in flight for them; cancel and let things settle first. A trial\ncounts, because it turns into a real charge on its own. A\n``customer.deleted`` event is emitted carrying the details as they were\nbefore erasure, so your own systems can match the record being erased.",
        "operationId": "purge_customer",
        "parameters": [
          {
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "title": "Customer Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerPurgeRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Purge Customer",
        "tags": [
          "customers"
        ]
      }
    },
    "/v1/customers/{customer_id}/vat_number": {
      "post": {
        "description": "Record a business customer's VAT registration number and check it.\n\nCall this when a customer tells you they are VAT registered, so their\nnext charge can be zero rated under the EU reverse charge. Every number\nis checked against the European Commission's VIES service before it\ncounts. Only a number that comes back valid enables the reverse charge;\na number that VIES cannot confirm is still stored, but tax is charged\nas normal until it can be confirmed.\n\nA number VIES rejects outright returns 400 and nothing is saved, so the\ncustomer keeps whatever registration they had before. VIES needs a\ncountry, so send ``country_code`` if the customer does not have one yet.\nSending ``vat_number`` as null clears the registration. Only the next\ncharge is affected; documents already issued are never repriced.",
        "operationId": "set_customer_vat_number",
        "parameters": [
          {
            "in": "path",
            "name": "customer_id",
            "required": true,
            "schema": {
              "title": "Customer Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerVatNumberRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Set Customer Vat Number",
        "tags": [
          "customers"
        ]
      }
    },
    "/v1/disputes": {
      "get": {
        "description": "List chargebacks raised against your payments, newest first.\n\nA dispute is created when a cardholder's bank pulls funds back. You\ncannot create or contest one through this API, and there is no evidence\nsubmission: disputes are recorded here so you can see money that has left\nand reconcile it.\n\nThere are only two statuses. ``open`` means the funds have been withdrawn.\n``won`` means they came back. There is no ``lost``, because the payment\nprovider gives no signal for it; a dispute you lost simply stays ``open``\nforever. Filter with ``status`` (comma-separated) or with ``payment_id``,\nwhich matches subscription payments only, not one-off charges.",
        "operationId": "list_disputes",
        "parameters": [
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "in": "query",
            "name": "payment_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Payment Id"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_DisputeResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Disputes",
        "tags": [
          "disputes"
        ]
      }
    },
    "/v1/disputes/{dispute_id}": {
      "get": {
        "description": "Retrieve one chargeback.\n\nA dispute belonging to another account returns 404, not 403.",
        "operationId": "get_dispute",
        "parameters": [
          {
            "in": "path",
            "name": "dispute_id",
            "required": true,
            "schema": {
              "title": "Dispute Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DisputeResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Dispute",
        "tags": [
          "disputes"
        ]
      }
    },
    "/v1/events": {
      "get": {
        "description": "List the events recorded for your account, newest first.\n\nAn event is the record of something that happened: a customer created, a\npayment paid, a subscription updated. The same records drive your webhook\nendpoints, so this is where you look when a webhook never arrived and you\nneed to know whether the event happened at all.\n\nThe optional ``type`` filter matches exactly, for example\n``type=customer.created``. There are no wildcards here; the ``*`` sentinel\nfor \"send me everything\" belongs on a webhook endpoint's enabled events,\nnot on this filter.",
        "operationId": "list_events",
        "parameters": [
          {
            "in": "query",
            "name": "type",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Type"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          },
          {
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 256,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Expand"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_EventResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Events",
        "tags": [
          "events"
        ]
      }
    },
    "/v1/events/stream": {
      "get": {
        "description": "Hold a connection open and receive this account's events as they happen.\n\nEach event arrives as a Server-Sent Events ``message`` frame whose data is\nthe same JSON that ``GET /v1/events/{id}`` returns, and whose ``id:`` field\nis the event id. Reach for this instead of polling ``GET /v1/events`` when\nyou want to react to events in near real time: a local webhook forwarder\nduring development, or a live view of what your account is doing.\n\nBy default the stream starts at the moment you connect, so events recorded\nbefore that are not replayed. To resume without gaps, pass the last event\nid you processed as ``starting_after``; every event after it is delivered\nin order before the stream goes live. Browsers do this for you, since an\n``EventSource`` replays the last ``id:`` it saw as the ``Last-Event-ID``\nheader, which this endpoint honours when ``starting_after`` is absent.\n``starting_after`` wins if both are present, and an id that does not name\none of your events is rejected with a 400 either way.\n\n``types`` is an optional comma-separated allow-list matched exactly, with\nno wildcards. Unknown types are rejected with a 400 naming them, for the\nsame reason ``enabled_events`` rejects them on a webhook endpoint: a filter\nthat silently matches nothing is indistinguishable from a quiet account,\nso a typo (or a Stripe spelling like ``customer.subscription.updated``)\nwould otherwise buy you a stream that stays empty forever and no way to\ntell why. The connection closes itself after about an hour with a\n``timeout`` frame, busy or not; reconnect with the last id you saw. This\nstream is not a substitute for webhook endpoints: nothing is retried, and\nanything recorded while you are disconnected is only recovered by resuming\nfrom a cursor.",
        "operationId": "stream_events",
        "parameters": [
          {
            "in": "query",
            "name": "types",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 512,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Types"
            }
          },
          {
            "description": "Resume after this event id instead of starting from now. The stream replays every event recorded after it, in order, then continues live. Unknown ids are rejected with a 400.",
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Resume after this event id instead of starting from now. The stream replays every event recorded after it, in order, then continues live. Unknown ids are rejected with a 400.",
              "title": "Starting After"
            }
          },
          {
            "description": "Standard SSE resume header, sent automatically by a browser EventSource on reconnect. Used only when starting_after is absent.",
            "in": "header",
            "name": "Last-Event-ID",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Standard SSE resume header, sent automatically by a browser EventSource on reconnect. Used only when starting_after is absent.",
              "title": "Last-Event-Id"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Stream Events",
        "tags": [
          "events"
        ]
      }
    },
    "/v1/events/{event_id}": {
      "get": {
        "description": "Retrieve one event, including the full data payload it carried.\n\nUse it to re-read what a webhook delivery contained, or to confirm the\nstate of a resource at the moment something happened to it. Events are\nwritten once and never change, so the payload is a snapshot from that\nmoment and will not match the resource's current state. An id belonging\nto another account returns 404, not 403.",
        "operationId": "get_event",
        "parameters": [
          {
            "in": "path",
            "name": "event_id",
            "required": true,
            "schema": {
              "title": "Event Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Event",
        "tags": [
          "events"
        ]
      }
    },
    "/v1/invoices": {
      "get": {
        "description": "List invoices, newest first.\n\nLine items are left out here to keep the response small. Fetch the\nindividual invoice when you need them.\n\n``customer_id``, ``subscription_id`` and ``payment_id`` each narrow\nto one, which is how you answer \"show me this customer's invoices\" or\n\"which invoice did this charge produce\" without paging the whole\naccount. ``status`` takes one of ``draft``, ``open``, ``paid``,\n``void``, ``uncollectible``.",
        "operationId": "list_invoices",
        "parameters": [
          {
            "in": "query",
            "name": "customer_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Customer Id"
            }
          },
          {
            "in": "query",
            "name": "subscription_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Subscription Id"
            }
          },
          {
            "in": "query",
            "name": "payment_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Payment Id"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 32,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          },
          {
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 256,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Expand"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_InvoiceResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Invoices",
        "tags": [
          "invoices"
        ]
      }
    },
    "/v1/invoices/{invoice_id}": {
      "get": {
        "description": "Retrieve one invoice, with its line items.\n\nThe list endpoint returns no line items, so this is where you come for\nthe breakdown of a charge. The tax figures and the billing name and\naddress are snapshots taken when the invoice was issued, so they will not\nfollow later edits to the customer. An invoice belonging to another\naccount returns 404, not 403.",
        "operationId": "get_invoice",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "title": "Invoice Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 256,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Expand"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Invoice",
        "tags": [
          "invoices"
        ]
      }
    },
    "/v1/invoices/{invoice_id}/email": {
      "post": {
        "description": "Send the customer their invoice again.\n\nThe same tenant-branded \"your invoice is ready\" email BillKit sends\nwhen the invoice is created, with a fresh portal link \u2014 the one in\nthe original email may have expired, and re-sending a dead link is\nworse than not re-sending at all.\n\nGoes to the address captured on the invoice, not the customer's\ncurrent one: this is a copy of a document that was issued to\nsomebody, and quietly redirecting it to a new address would make the\nresend a different act from the original send. An invoice with no\naddress on file returns 400 rather than reporting a send that did\nnot happen.",
        "operationId": "email_invoice",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceEmailResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Email Invoice",
        "tags": [
          "invoices"
        ]
      }
    },
    "/v1/invoices/{invoice_id}/pdf": {
      "get": {
        "description": "Download the invoice as a PDF.\n\nThis is the document you give a customer or their accountant. The PDF is\nrendered the first time it is asked for and reused afterwards, so the\nfirst request for a given invoice is slower than the rest.\n\nDepending on how the service is configured you will either receive the\nPDF bytes directly or a redirect to a short-lived download link, so\nfollow redirects. If PDF rendering is not available you get a 501 whose\nbody carries the full invoice data, which is enough to produce your own\ndocument.",
        "operationId": "get_invoice_pdf",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Invoice Pdf",
        "tags": [
          "invoices"
        ]
      }
    },
    "/v1/invoices/{invoice_id}/void": {
      "post": {
        "description": "Void an invoice, stating that the sale was never owed.\n\nUse this for an invoice that should not have been issued \u2014 a period\nmetered wrong, a customer billed by mistake, an amount you have decided\nnot to collect. The invoice keeps its number and stays readable, because\na gapless series cannot have a row removed from it; it simply stops\nbeing a receivable, and ``invoice.voided`` fires.\n\n**A paid invoice cannot be voided**, and the refusal is deliberate rather\nthan a limitation: voiding claims nothing was ever owed, which is not\ntrue once the money has moved. Refund the payment instead \u2014 a settled\nrefund issues a credit note against this invoice, which is the document\nthat reverses a sale that really happened.\n\nVoiding is idempotent: re-voiding an already-void invoice returns it\nunchanged and emits nothing a second time. A charge still in flight\nagainst the invoice is refused with ``operation_pending``; wait for it\nto settle or fail.\n\nUsage already invoiced here stays attached to it and is never re-billed\non a later period close.",
        "operationId": "void_invoice_route",
        "parameters": [
          {
            "in": "path",
            "name": "invoice_id",
            "required": true,
            "schema": {
              "title": "Invoice Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "anyOf": [
                  {
                    "$ref": "#/components/schemas/InvoiceVoid"
                  },
                  {
                    "type": "null"
                  }
                ],
                "title": "Body"
              }
            }
          }
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Void Invoice Route",
        "tags": [
          "invoices"
        ]
      }
    },
    "/v1/metrics/home": {
      "get": {
        "description": "Four headline numbers for your account, in one call.\n\nReturns monthly recurring revenue, active subscriptions, today's revenue\nand failed payments in the last 24 hours. Each comes with the change\nagainst the comparison period and 30 days of history for a sparkline, so\nyou can render a dashboard without doing your own aggregation.\n\nEvery figure is as-of-now. Monthly recurring revenue and active\nsubscriptions used to come from a nightly snapshot and lagged by up to\na day; they are computed live now, so cancelling a subscription is\nreflected on the next load. The 30-day sparklines and the deltas still\ncome from the daily rollup, which is the one thing that genuinely\ncannot be recomputed on demand.\n\nMonthly recurring revenue is **net of discounts**: a subscription\ncarrying a forever or repeating coupon contributes what it is actually\nbilled, not its list price. Only ``active`` subscriptions count;\ntrialing ones do not.",
        "operationId": "get_home_metrics",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HomeMetricsResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Home Metrics",
        "tags": [
          "metrics"
        ]
      }
    },
    "/v1/payments": {
      "get": {
        "description": "List subscription payments, newest first.\n\nPass ``customer_id`` to narrow to one customer. Failed and pending\nattempts are included alongside successful ones, so check ``status``\nbefore treating a row as revenue. One-off charges are not listed here.\n\n**Mandate verifications are not listed.** A card re-authorisation, an\nimport activation and a wallet setup each charge a token amount to\nprove an instrument works, and the provider reverses it. Nothing was\nsold, so they are not payments in the sense this list means \u2014 and an\nabandoned one (the customer opened \"Update payment method\" and closed\nthe tab) sits at ``expired``, which read on this screen as a customer\nwhose card had failed. The rows are still written: they are the audit\ntrail of a real provider interaction and what webhook correlation and\nidempotency key off. They are just not purchases.\n\nThis matches the billing portal's ledger, which has always excluded\nthem \u2014 the same non-event was hidden from the customer and shown to\nthe operator.",
        "operationId": "list_payments",
        "parameters": [
          {
            "in": "query",
            "name": "customer_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Customer Id"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          },
          {
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 256,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Expand"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_PaymentResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Payments",
        "tags": [
          "payments"
        ]
      }
    },
    "/v1/payments/{payment_id}": {
      "get": {
        "description": "Retrieve one subscription payment, including how much has been refunded.\n\nThis covers charges tied to a subscription: the first one, renewals, plan\nchanges, payment-method verifications and metered cycles. One-off charges\nare separate and live under ``GET /v1/checkout/one_shot/{id}``.\n\n``amount_refunded_cents`` counts refunds that are pending as well as\nsucceeded, so it matches what ``POST /v1/refunds`` will still let you take.\nA payment belonging to another account returns 404, not 403.",
        "operationId": "get_payment",
        "parameters": [
          {
            "in": "path",
            "name": "payment_id",
            "required": true,
            "schema": {
              "title": "Payment Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 256,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Expand"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Payment",
        "tags": [
          "payments"
        ]
      }
    },
    "/v1/payments/{payment_id}/provider": {
      "get": {
        "description": "Fetch the provider's own record of this charge, live.\n\nSupport work asks questions BillKit's copy of a payment cannot\nanswer: which card BIN, which iDEAL bank, what the provider's own\nstatus string says, what it put in ``details``. This reads it from\nMollie at request time rather than from a stored copy, so it is\nalways current and BillKit keeps no second copy of provider-side\npersonal data.\n\nReading live has one consequence worth stating: it can fail. Mollie\nbeing down, a credential that no longer authorises this profile, or\na payment old enough to have aged out all return\n``available: false`` with a short reason, and a 200 \u2014 the payment\nitself is not in doubt, only our ability to look it up right now, so\na caller renders the rest of the page regardless.",
        "operationId": "get_payment_provider_payload",
        "parameters": [
          {
            "in": "path",
            "name": "payment_id",
            "required": true,
            "schema": {
              "title": "Payment Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProviderPayloadResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Payment Provider Payload",
        "tags": [
          "payments"
        ]
      }
    },
    "/v1/ping": {
      "get": {
        "operationId": "ping",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "title": "Response Ping",
                  "type": "object"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Ping",
        "tags": [
          "meta"
        ]
      }
    },
    "/v1/prices": {
      "get": {
        "description": "List your prices, newest first.\n\nPass ``product_id`` to get just one product's prices. Filter here rather\nthan in your own code: this endpoint is paginated, so filtering a single\npage yourself quietly misses anything past the limit.",
        "operationId": "list_prices",
        "parameters": [
          {
            "in": "query",
            "name": "product_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Product Id"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_PriceResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Prices",
        "tags": [
          "prices"
        ]
      },
      "post": {
        "description": "Create a price, which is what a customer actually buys.\n\nA price pins an amount, a currency and a billing interval to a product.\nIt is also where you set the trial length, the payment methods you accept\nfor it, the refund window, and whether ``amount_cents`` includes tax or\nhas tax added on top. Those settings are read at checkout, so get them\nright before you start selling.\n\nA price's amount, currency and interval are fixed at creation. To\ncharge something different, create a new price and point new checkouts\nat it, then archive the old one by sending ``active: false`` to\n``POST /v1/prices/{id}``; customers on it stay on it until they move.\nThe product must exist and must not be archived.\n\n**How the amount is expressed** depends on what you are selling.\n\nA plan sends ``amount_cents``: whole minor units, charged every period.\n\nA meter (``usage_type: \"metered\"``) can instead send\n``unit_amount_decimal``, a per-unit rate in minor units with up to 12\ndecimal places, as a **string**. ``\"0.02\"`` is 0.02 cents, i.e. \u20ac0.0002\nper unit. Send it as a string and read it back as a string: a JSON\nnumber would be a double in most clients, and these values have no\nexact binary form. The period's whole quantity is multiplied by the\nrate and rounded once, at the invoice.\n\nA meter can also price by bands, with ``billing_scheme: \"tiered\"`` plus\n``tiers`` and ``tiers_mode``. ``graduated`` prices the units inside\neach band; ``volume`` lets the total pick one band, which then prices\nevery unit. The same table under the two modes is a different bill, so\nthe mode is required. The last band must be open-ended (``up_to:\n\"inf\"``), and a tiered price sends no ``amount_cents``.",
        "operationId": "create_price",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PriceCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Price",
        "tags": [
          "prices"
        ]
      }
    },
    "/v1/prices/{price_id}": {
      "get": {
        "description": "Retrieve one price, including its trial, tax and refund-window settings.\n\nA price belonging to another account returns 404, not 403.",
        "operationId": "get_price",
        "parameters": [
          {
            "in": "path",
            "name": "price_id",
            "required": true,
            "schema": {
              "title": "Price Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Price",
        "tags": [
          "prices"
        ]
      },
      "post": {
        "description": "Archive a price so it stops selling, or put it back on sale.\n\nSend ``active: false`` to archive. The price keeps its id and is still\nreturned by ``GET /v1/prices/{id}`` and by listings, because\nsubscriptions renew against it by id and the amount they are charged\nhas to stay readable.\n\nCustomers already on the price are unaffected and keep renewing at it.\nWhat stops is new business: a checkout session against this price is\nrefused, and the price is no longer offered as a plan change.\n\nSend ``active: true`` to undo that. Prices are immutable in the fields\nthat decide money, so archiving and un-archiving cannot change what\nanyone was charged, which is why both directions are allowed. If the\nproduct above the price is archived, un-archiving the price alone will\nnot sell it; un-archive the product too.\n\nThe editable fields are the forward-looking ones. ``amount_cents``,\n``currency``, ``interval`` and ``usage_type`` are fixed at creation \u2014\nsubscriptions renew against a price by id, so changing any of them\nwould re-price live customers and make an issued invoice unreadable.\nTo charge something different, create a new price and point new\ncheckouts at it.\n\nWhat you can change: ``active``, ``metadata``, ``payment_methods``,\nand the refund policy (``refund_on_cancel``,\n``refund_window_initial_days``, ``refund_window_renewal_days``). The\nrefund fields are evaluated when a cancellation or refund happens, so\nsetting them here covers the customers already on the price rather\nthan only new ones.\n\n``tax_behavior`` moves **one way**: it can be set while it is\n``unspecified`` and never changed afterwards, because flipping it\nwould restate whether tax was inside or on top of an amount somebody\nhas already paid.\n\nOmitted fields are left alone, and sending values a price already has\nreturns it unchanged and emits no second event. Archiving emits\n``price.archived``; every other change emits ``price.updated``.",
        "operationId": "update_price",
        "parameters": [
          {
            "in": "path",
            "name": "price_id",
            "required": true,
            "schema": {
              "title": "Price Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PriceUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PriceResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Price",
        "tags": [
          "prices"
        ]
      }
    },
    "/v1/products": {
      "get": {
        "description": "List your products, newest first.\n\nArchived products are included, so filter on ``active`` yourself if you\nare rendering a pricing page from this.\n\n``expand=prices`` attaches every price on each product (archived ones\ntoo, active first). ``expand=stats`` attaches the live subscriber\ncount and normalised MRR. Both resolve in one query for the whole\npage, so asking for them costs two queries, not two per product.",
        "operationId": "list_products",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          },
          {
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 256,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Expand"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_ProductResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Products",
        "tags": [
          "products"
        ]
      },
      "post": {
        "description": "Create a product, the thing you sell.\n\nA product carries the name and description a customer sees. It has no\nprice of its own, so create one here and then attach one or more prices\nto it with ``POST /v1/prices``. Use a separate product per distinct\noffering, and separate prices under it for monthly against yearly or for\ndifferent currencies.",
        "operationId": "create_product",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Product",
        "tags": [
          "products"
        ]
      }
    },
    "/v1/products/{product_id}": {
      "get": {
        "description": "Retrieve one product.\n\nArchived products are still returned, with ``active: false``. A product\nbelonging to another account returns 404, not 403.",
        "operationId": "get_product",
        "parameters": [
          {
            "in": "path",
            "name": "product_id",
            "required": true,
            "schema": {
              "title": "Product Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 256,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Expand"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Product",
        "tags": [
          "products"
        ]
      },
      "post": {
        "description": "Update a product's details, or archive it.\n\nOnly the fields you send change. ``metadata`` and ``marketing_features``\nare replaced wholesale rather than merged.\n\nSending ``active: false`` archives the product, which is how you stop\noffering it. Archiving stops new business: a checkout session against\nany of the product's prices is refused, the product is no longer\noffered as a plan change in the billing portal, and you can no longer\ncreate prices under it. Customers already subscribed are unaffected and\nkeep renewing. The product keeps its id and still appears in listings\nand in ``GET /v1/products/{id}`` with ``active: false``, so what was\nsold under it stays readable. It emits ``product.archived`` rather than\n``product.updated``.\n\nThe prices under it keep their own ``active: true``, so archive them\nindividually with ``POST /v1/prices/{id}`` if you want that reflected\non the price. Sending ``active: true`` un-archives, which is how you\nundo an archive.",
        "operationId": "update_product",
        "parameters": [
          {
            "in": "path",
            "name": "product_id",
            "required": true,
            "schema": {
              "title": "Product Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Product",
        "tags": [
          "products"
        ]
      }
    },
    "/v1/refunds": {
      "get": {
        "description": "List refunds, newest first.\n\nCovers refunds against subscription payments and against one-off\npayments alike. There are no filters here, so to find the refunds on a\nparticular charge read ``amount_refunded_cents`` on the payment itself.",
        "operationId": "list_refunds",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_RefundResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Refunds",
        "tags": [
          "refunds"
        ]
      },
      "post": {
        "description": "Refund a payment, in full or in part.\n\nName exactly one target: ``payment_id`` for a subscription charge,\n``one_shot_payment_id`` for a one-off, or ``subscription_id`` as a\nshorthand for that subscription's most recent payment. Omit\n``amount_cents`` to refund whatever is still refundable; send it to\nrefund less. Repeated partial refunds are allowed up to the original\namount, and anything beyond it is a 400.\n\nRefunding a subscription payment in full cancels the subscription\nimmediately, which is the only way to end one before its period is up. A\npartial refund leaves it running, and fully refunding a metered cycle\nnever cancels, since that corrects a bill rather than ending the service.\n\nThe refund is usually not settled when this returns. It normally comes\nback ``pending`` and reaches ``succeeded`` or ``failed`` later, so handle\nthe ``refund.failed`` event rather than reading a 200 as money having\nmoved.\n\nRefunds are bounded by the refund window configured on the price, and a\npayment past that window is refused with a 400 however much is left on it.",
        "operationId": "create_refund",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RefundCreateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefundResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Refund",
        "tags": [
          "refunds"
        ]
      }
    },
    "/v1/refunds/{refund_id}": {
      "get": {
        "description": "Retrieve one refund and check whether it has settled.\n\n``status`` is one of ``pending``, ``succeeded`` or ``failed``. It is our\nown three-value vocabulary, not the payment provider's, so you do not\nhave to handle the provider's wider set. A refund belonging to another\naccount returns 404, not 403.",
        "operationId": "get_refund",
        "parameters": [
          {
            "in": "path",
            "name": "refund_id",
            "required": true,
            "schema": {
              "title": "Refund Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefundResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Refund",
        "tags": [
          "refunds"
        ]
      }
    },
    "/v1/subscriptions": {
      "get": {
        "description": "List subscriptions, newest first.\n\nThere is no way to create a subscription directly. One appears here only\nafter a customer completes a checkout and the payment settles, so a\ncheckout session you just created has no subscription yet.\n\n``customer_id`` narrows to one customer. ``status`` and\n``renewal_state`` each take a comma-separated list, for example\n``status=active,past_due``. An unrecognised value is a 400 naming the\nones that work, rather than being silently ignored.\n\nThe two filters answer different questions. ``status`` is where the\nsubscription stands with its payments: ``incomplete``, ``trialing``,\n``active``, ``past_due``, ``canceled``. ``renewal_state`` is what\nhappens at the end of the current period: ``auto_renew``, ``paused``,\n``canceling``, ``stopped``. A paused subscription still reads as\n``active``, because the customer has paid for the period they are in,\nso ``renewal_state=paused`` is how you find paused ones.",
        "operationId": "list_subscriptions",
        "parameters": [
          {
            "in": "query",
            "name": "customer_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 64,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Customer Id"
            }
          },
          {
            "in": "query",
            "name": "status",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Status"
            }
          },
          {
            "in": "query",
            "name": "renewal_state",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Renewal State"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          },
          {
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 256,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Expand"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_SubscriptionResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Subscriptions",
        "tags": [
          "subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{subscription_id}": {
      "get": {
        "description": "Retrieve one subscription.\n\nRead ``status`` together with ``cancel_at_period_end`` and\n``current_period_end``. A subscription that has been cancelled stays\n``active`` with ``cancel_at_period_end: true`` until the period it is\npaid through runs out, and only then becomes ``canceled``. Treating\n``active`` alone as \"this customer is staying\" will mislead you.\n\nA subscription belonging to another account returns 404, not 403.",
        "operationId": "get_subscription",
        "parameters": [
          {
            "in": "path",
            "name": "subscription_id",
            "required": true,
            "schema": {
              "title": "Subscription Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "expand",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 256,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Expand"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Subscription",
        "tags": [
          "subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{subscription_id}/cancel": {
      "post": {
        "description": "Stop a subscription renewing at the end of the current period.\n\nCancellation is always at period end. There is no immediate-cancel\noption and no parameter to ask for one. The customer keeps access until\n``current_period_end``, the response still shows ``status: active`` with\n``cancel_at_period_end: true``, and the status only becomes ``canceled``\nonce that date passes. If you need the customer cut off now, refund the\npayment in full instead, which cancels immediately.\n\nCalling it twice is safe and returns the subscription unchanged. The\ncustomer is sent a cancellation email if they have an address on file.\nUse ``POST /v1/subscriptions/{id}/reactivate`` to undo it while the\nperiod is still running.",
        "operationId": "cancel_subscription",
        "parameters": [
          {
            "in": "path",
            "name": "subscription_id",
            "required": true,
            "schema": {
              "title": "Subscription Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Cancel Subscription",
        "tags": [
          "subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{subscription_id}/pause": {
      "post": {
        "description": "Stop a subscription renewing, without ending it.\n\nUse this when a customer wants a break rather than out. Renewals stop,\nthe customer keeps access until ``current_period_end``, and any pending\ncancellation is cleared. Resume it later with\n``POST /v1/subscriptions/{id}/resume``.\n\nPausing shows up in ``renewal_state``, which becomes ``paused``.\n``status`` stays ``active``, so read ``renewal_state`` to tell a paused\nsubscription from a renewing one. Pausing is refused on a cancelled\nsubscription and on metered prices. Pausing an already-paused\nsubscription returns it unchanged.\n\nThere is a deadline on resuming. Once ``current_period_end`` has passed\nthe subscription can no longer be resumed and the customer has to go\nthrough checkout again, so a long pause is effectively a cancellation.",
        "operationId": "pause_subscription",
        "parameters": [
          {
            "in": "path",
            "name": "subscription_id",
            "required": true,
            "schema": {
              "title": "Subscription Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Pause Subscription",
        "tags": [
          "subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{subscription_id}/preview_update": {
      "post": {
        "description": "Quote what moving this subscription to another price would cost.\n\nShow this to the customer before they confirm a plan change. It returns\nthe credit for the unused part of the current period, the amount that\nwould be charged now with tax broken out, and the new period end. It\nwrites nothing and charges nothing, so it is safe to call as often as you\nlike.\n\nCheck ``refused`` in the response. It comes back true when the credit\nnearly covers the new price, which happens when the renewal is close.\n``POST /v1/subscriptions/{id}/update`` rejects the change in that case, so\na refused quote means the answer is to wait for the renewal rather than\nto retry. The quote is advisory: the amount is recalculated when you\nactually run the update, so it can differ if time has passed.",
        "operationId": "preview_update_subscription",
        "parameters": [
          {
            "in": "path",
            "name": "subscription_id",
            "required": true,
            "schema": {
              "title": "Subscription Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlanChangePreviewRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlanChangePreviewResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Preview Update Subscription",
        "tags": [
          "subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{subscription_id}/reactivate": {
      "post": {
        "description": "Undo a pending cancellation and keep the subscription renewing.\n\nUse this when a customer changes their mind after cancelling, while the\nperiod they paid for is still running. It clears\n``cancel_at_period_end`` and puts renewals back on.\n\nIt does the same work as ``resume`` and carries the same two conditions:\n``current_period_end`` must still be in the future, and the customer's\npayment method must still be authorised. It exists separately so your\naudit log records a reversed cancellation rather than an unpaused\nsubscription. Reactivating a subscription that is already renewing\nreturns it unchanged.",
        "operationId": "reactivate_subscription",
        "parameters": [
          {
            "in": "path",
            "name": "subscription_id",
            "required": true,
            "schema": {
              "title": "Subscription Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Reactivate Subscription",
        "tags": [
          "subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{subscription_id}/reauthorize_payment_method": {
      "post": {
        "description": "Start the flow for a customer to replace their payment method.\n\nReach for this when a renewal has failed or a card is expiring. It\nreturns a ``checkout_url``; send the customer there and they authorise a\nnew payment method by completing a small verification charge, whose\namount and currency are in the response.\n\nIt does not change the subscription. The new payment method is recorded\nonly once the customer finishes and the payment provider confirms it, so\ndo not treat a 200 here as the method having been updated. Watch for the\n``subscription.payment_method_updated`` event instead. A past-due\nsubscription is cleared at that point, not at this one. Refused on a\ncancelled subscription and on one whose first checkout never completed.",
        "operationId": "reauthorize_payment_method",
        "parameters": [
          {
            "in": "path",
            "name": "subscription_id",
            "required": true,
            "schema": {
              "title": "Subscription Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ReauthorizationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReauthorizationResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Reauthorize Payment Method",
        "tags": [
          "subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{subscription_id}/resume": {
      "post": {
        "description": "Restart renewals on a paused subscription.\n\nBilling picks up from ``current_period_end``, so the customer is not\ncharged now and does not lose the time they already paid for.\n\nTwo things must still hold, and both return 400 if they do not. The\nperiod must not have run out yet: once ``current_period_end`` is in the\npast there is nothing to resume and the customer has to check out again.\nAnd the customer's payment method must still be authorised; if it is not,\nsend them through ``POST /v1/subscriptions/{id}/reauthorize_payment_method``\nfirst. Resuming a subscription that is already renewing returns it\nunchanged.",
        "operationId": "resume_subscription",
        "parameters": [
          {
            "in": "path",
            "name": "subscription_id",
            "required": true,
            "schema": {
              "title": "Subscription Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Resume Subscription",
        "tags": [
          "subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{subscription_id}/update": {
      "post": {
        "description": "Move a subscription to a different price, charging the difference now.\n\nThis starts the plan change; it does not complete it. The prorated\ndifference is charged against the customer's existing payment method, and\nthe subscription only moves to the new price once that charge settles.\nThe response is the subscription as it still is, on the old price, so do\nnot read it back as confirmation. Wait for the ``subscription.updated``\nevent, or poll ``GET /v1/subscriptions/{id}`` until ``price_id`` changes.\n\nThe amount is recomputed here rather than taken from your preview. The\nsubscription must be renewing normally, not paused or cancelling, and the\ncustomer must have an authorised payment method. The new price has to be\nactive and in the same currency, and neither price may be metered. If the\nrenewal is close enough that the credit nearly covers the new price the\nchange is refused with a 400; wait for the renewal instead.",
        "operationId": "update_subscription",
        "parameters": [
          {
            "in": "path",
            "name": "subscription_id",
            "required": true,
            "schema": {
              "title": "Subscription Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlanChangeUpdateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubscriptionResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Subscription",
        "tags": [
          "subscriptions"
        ]
      }
    },
    "/v1/subscriptions/{subscription_id}/usage_records": {
      "get": {
        "description": "List the usage reported against one metered subscription.\n\nThis is the reconciliation view. Pass ``invoice_id=pending`` to see what\nthe next period close will bill, or a specific invoice id to see exactly\nwhich records made up a line on it. Without the filter you get every\nrecord, billed or not.\n\nA record carrying ``written_off_at`` is not pending and is left out of\nthat filter. It is usage the subscription stopped billing before a\nclose could pick it up \u2014 an exhausted retry ladder, or a final close\nunder the provider minimum \u2014 so it is reported as what it is rather\nthan as a charge that is still coming.\n\nThe subscription must exist and be on a metered price. A subscription\nthat is not metered is a 400 and one belonging to another account is a\n404, rather than an empty page that would read as \"no usage\".",
        "operationId": "list_usage_records",
        "parameters": [
          {
            "in": "path",
            "name": "subscription_id",
            "required": true,
            "schema": {
              "title": "Subscription Id",
              "type": "string"
            }
          },
          {
            "description": "Filter by billing state: 'pending' for records not yet invoiced, or an invoice id for the records it billed.",
            "in": "query",
            "name": "invoice_id",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by billing state: 'pending' for records not yet invoiced, or an invoice id for the records it billed.",
              "title": "Invoice Id"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_UsageRecordResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Usage Records",
        "tags": [
          "usage_records"
        ]
      },
      "post": {
        "description": "Report usage against a metered subscription.\n\nPost one record each time the customer consumes something you charge for.\nRecords are cheap to write and are added up at the end of the billing\nperiod, when they become a single invoice line. Nothing is charged at the\nmoment you report.\n\nThe subscription must be on a metered price, and must be active or past\ndue; past due is accepted so a failed charge does not lose you the meter\nreading. ``occurred_at`` may be backdated within the subscription's\nlifetime but not set in the future.\n\nRecords cannot be changed or deleted once written, so dedupe on the way\nin. There are two ways, and they cover different failures. An\n``Idempotency-Key`` header covers a retry of *this HTTP request*. The\n``identifier`` field covers a retry of *your own call* \u2014 a job runner\nreplaying a task, a queue delivering twice, your code re-invoking after\na timeout \u2014 which arrives here as a genuinely new request with a new\nkey. Send the id of whatever you are metering as ``identifier`` and a\nsecond report of it returns the first record unchanged, so it is billed\nonce.",
        "operationId": "create_usage_record",
        "parameters": [
          {
            "in": "path",
            "name": "subscription_id",
            "required": true,
            "schema": {
              "title": "Subscription Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UsageRecordCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageRecordResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Usage Record",
        "tags": [
          "usage_records"
        ]
      }
    },
    "/v1/subscriptions/{subscription_id}/usage_summary": {
      "get": {
        "description": "See what the next period close will bill, before it bills it.\n\nListing usage records tells you the quantity. This tells you the\nmoney: the pending quantity priced through the same rate or tier table\nthe close uses, with VAT resolved the same way, plus the one thing\nthat surprises people.\n\nThat thing is ``will_charge``. A period whose total is under\n``minimum_charge_cents`` is not charged at all, because the payment\nprovider would refuse it. The usage is not lost \u2014 it stays pending and\nrolls into the next period, which is then billed for both. But a\ntenant expecting a small invoice and receiving nothing had no way to\nsee that from the API, so this is where it says so.\n\n``open_invoice_id`` is an earlier cycle that is invoiced and still\nunsettled. While one is open, this period cannot be charged.",
        "operationId": "get_usage_summary",
        "parameters": [
          {
            "in": "path",
            "name": "subscription_id",
            "required": true,
            "schema": {
              "title": "Subscription Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UsageSummaryResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Usage Summary",
        "tags": [
          "usage_records"
        ]
      }
    },
    "/v1/tax_rates": {
      "get": {
        "description": "List tax rates, newest first.\n\nRetired rates are included with ``active: false``, so a country can\nappear more than once. The one that applies today is the active one.",
        "operationId": "list_tax_rates",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_TaxRateResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Tax Rates",
        "tags": [
          "tax_rates"
        ]
      },
      "post": {
        "description": "Set the VAT rate to charge customers in one country.\n\nConfigure a rate for each country you sell into. Without one, customers\nthere are charged no tax. The rate is in basis points, so 2100 means 21\npercent. ``inclusive`` says whether your prices already contain the tax\nor it should be added on top.\n\nCreating a rate for a country that already has one automatically retires\nthe old rate rather than replacing it. The old row is kept so charges\nmade under it still reconcile. Rates apply to charges made from now on\nand never reprice anything already invoiced.",
        "operationId": "create_tax_rate",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaxRateCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaxRateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Tax Rate",
        "tags": [
          "tax_rates"
        ]
      }
    },
    "/v1/tax_rates/{tax_rate_id}": {
      "get": {
        "description": "Retrieve one tax rate.\n\nRetired rates are still readable, with ``active: false``, so a charge can\nbe traced back to the rate it was made under. A rate belonging to\nanother account returns 404, not 403.",
        "operationId": "get_tax_rate",
        "parameters": [
          {
            "in": "path",
            "name": "tax_rate_id",
            "required": true,
            "schema": {
              "title": "Tax Rate Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaxRateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Tax Rate",
        "tags": [
          "tax_rates"
        ]
      },
      "post": {
        "description": "Correct a tax rate, retire it, or bring a retired one back into use.\n\nOnly the fields you send change, and the country cannot be changed at\nall. Prefer creating a new rate when a country's VAT genuinely changes,\nso the old charges stay traceable to the rate that produced them; edit in\nplace only to fix a rate that was entered wrong.\n\nSending ``active: false`` retires the rate and is how you stop charging\nVAT in a country. The rate stays readable, because an invoice records\nthe percentage it charged and you have to be able to point at the rate\nthat produced it. If it was the country's only active rate, customers\nthere are charged no tax from then on, so retire only when you genuinely\nstop collecting VAT in that country.\n\nSending ``active: true`` on a retired rate makes it current again and\nretires whichever rate currently holds that country, since a country can\nonly have one active rate. Nothing already invoiced is repriced.",
        "operationId": "update_tax_rate",
        "parameters": [
          {
            "in": "path",
            "name": "tax_rate_id",
            "required": true,
            "schema": {
              "title": "Tax Rate Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaxRateUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaxRateResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Tax Rate",
        "tags": [
          "tax_rates"
        ]
      }
    },
    "/v1/tenant/billing_profile": {
      "get": {
        "description": "Read your own registered country and VAT number.\n\nThese are what your customers' VAT is decided against, so check them\nbefore you take your first live payment. ``country_code`` is what you\nhave stored and can be null; ``effective_country_code`` is what the next\ncharge will actually use. The two differ only when you have stored\nnothing, which is exactly the case worth spotting.\n\n``vat_id`` is your own VAT registration, or null if you have none. It has\nno effective counterpart, because nothing can stand in for a real\nregistration number.",
        "operationId": "get_billing_profile",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantBillingProfileResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Billing Profile",
        "tags": [
          "tenant"
        ]
      },
      "post": {
        "description": "Set your registered country, and optionally your own VAT number.\n\nSet this before you charge anyone. The country decides whether a\ncustomer's sale is domestic, cross-border within the EU, or outside it,\nand so what VAT applies to them.\n\n``country_code`` is required on every call. ``vat_id`` is optional: omit\nit and your stored registration is left alone, or send it as null to\nclear it, since ceasing to be VAT registered is a real event worth\nrecording.\n\nChanges take effect on your next charge only. Tax is worked out before\nmoney moves and written onto the payment and its invoice, and nothing\ngoes back and recalculates it, so correcting a country here never\nreprices a document that has already been issued.",
        "operationId": "update_billing_profile",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantBillingProfileUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantBillingProfileResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Billing Profile",
        "tags": [
          "tenant"
        ]
      }
    },
    "/v1/tenant/capabilities": {
      "get": {
        "description": "Read which payment methods and currencies your account can actually use.\n\nCall this before offering a payment method at checkout, since what you\ncan take depends on what your payment provider has approved for you, not\non what BillKit supports. Also tells you whether a provider account is\nconnected at all.\n\nThe lists are cached rather than fetched live, and\n``provider_capabilities_refreshed_at`` says when they were last refreshed\nso you can show the age honestly. Until the first refresh lands that\ntimestamp is null and both lists are empty, which means \"not known yet\",\nnot \"nothing enabled\"; retry shortly rather than treating it as a final\nanswer.",
        "operationId": "get_tenant_capabilities",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCapabilitiesResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Tenant Capabilities",
        "tags": [
          "tenant"
        ]
      }
    },
    "/v1/tenant/export": {
      "get": {
        "description": "Download everything in your account as one JSON file.\n\nThis is your data-portability route under GDPR Article 20, and it is also\nhow you take a backup or move off BillKit. It covers customers,\nsubscriptions, payments, refunds, invoices with their line items, and\nevents. Each record has the same shape the matching ``GET`` route\nreturns, so you can read it back with the same models.\n\nThe response streams and can be large, so write it to a file rather than\nholding it in memory. Test and live data are exported separately: you get\nwhichever the key you call with belongs to, so run it twice for both.\nNothing is changed by exporting, but the access is recorded in your audit\nlog.",
        "operationId": "export_tenant_data",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {}
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Export Tenant Data",
        "tags": [
          "tenant"
        ]
      }
    },
    "/v1/tenant/portal_branding": {
      "get": {
        "description": "Read how your billing portal is branded.\n\nReturns exactly what you have configured, with anything you have never\nset coming back as null. Nothing is filled in with defaults here, on\npurpose: this is the endpoint for rendering a settings form, where \"not\nconfigured\" and \"configured to the default value\" have to look different.\nWhat the customer actually sees is on the same payload, under the\n``effective_*`` fields.",
        "operationId": "get_portal_branding",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantPortalBrandingResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "Get Portal Branding",
        "tags": [
          "tenant"
        ]
      },
      "post": {
        "description": "Set the business name, logo, support email and colours your customers\nsee in the billing portal.\n\nOnly the fields you send change. Sending a field as null clears it and\nfalls back to the default, which is different from omitting it. Changes\napply to portal sessions already open, not just new ones.",
        "operationId": "update_portal_branding",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantPortalBrandingUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantPortalBrandingResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Portal Branding",
        "tags": [
          "tenant"
        ]
      }
    },
    "/v1/tenant/provider_credential": {
      "post": {
        "description": "Replace the payment provider API key BillKit uses to charge on your\nbehalf.\n\nUse it after rotating the key at your provider, so charges keep working.\nThe key is stored encrypted and is never returned by any endpoint,\nincluding this one. Sending the same key twice is harmless and leaves you\nin the same state.\n\nOne key is held per mode, so test and live are separate. ``mode`` defaults\nto the mode of the key you are calling with; set it explicitly to rotate\nyour live key from a test-mode session. Get this wrong and charges in that\nmode stop working, so verify the key with your provider first.",
        "operationId": "rotate_tenant_provider_credential",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantProviderCredentialRotateRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantProviderCredentialResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Rotate Tenant Provider Credential",
        "tags": [
          "tenant"
        ]
      }
    },
    "/v1/test_clocks": {
      "get": {
        "description": "List your test clocks, newest first. Test mode only.",
        "operationId": "list_test_clocks",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_TestClockResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Test Clocks",
        "tags": [
          "test_clocks"
        ]
      },
      "post": {
        "description": "Create a frozen clock so you can test billing over time.\n\nAttach customers to a clock and then move it forward to watch trials end,\nrenewals charge and dunning run, without waiting a month. Pass the clock\nid as ``test_clock`` when creating a customer; only customers created\nthat way follow it.\n\nTest mode only. A live key is refused whatever its scopes, so there is no\nway to move production billing forward by accident.",
        "operationId": "create_test_clock",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TestClockCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestClockResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Test Clock",
        "tags": [
          "test_clocks"
        ]
      }
    },
    "/v1/test_clocks/{test_clock_id}": {
      "delete": {
        "description": "Delete a test clock.\n\nThe row is really removed, so the response is a deletion marker rather\nthan the clock. Customers attached to the clock are not deleted; they\nare detached and go back to running on real time. Test mode only.",
        "operationId": "delete_test_clock",
        "parameters": [
          {
            "in": "path",
            "name": "test_clock_id",
            "required": true,
            "schema": {
              "title": "Test Clock Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Test Clock",
        "tags": [
          "test_clocks"
        ]
      },
      "get": {
        "description": "Retrieve one test clock and the time it is currently frozen at.\n\nTest mode only. A clock belonging to another account returns 404.",
        "operationId": "get_test_clock",
        "parameters": [
          {
            "in": "path",
            "name": "test_clock_id",
            "required": true,
            "schema": {
              "title": "Test Clock Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestClockResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Test Clock",
        "tags": [
          "test_clocks"
        ]
      }
    },
    "/v1/test_clocks/{test_clock_id}/advance": {
      "post": {
        "description": "Move a test clock forward and let everything due in between happen.\n\nThis is what makes a test clock useful. Advancing past a trial end, a\nmetered period close, a dunning deadline or a one-off payment's expiry\nmakes each of those fire, for this clock's customers only. The work runs\nbefore the response returns, so by the time you get a 200 you can read\nthe results back.\n\nA clock only ever moves forward; a target at or before the current time\nis a 400. Advancing does not make the payment provider charge anyone, so\na renewal that would need a real charge does not produce one. Test mode\nonly.",
        "operationId": "advance_test_clock",
        "parameters": [
          {
            "in": "path",
            "name": "test_clock_id",
            "required": true,
            "schema": {
              "title": "Test Clock Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TestClockAdvance"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TestClockResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Advance Test Clock",
        "tags": [
          "test_clocks"
        ]
      }
    },
    "/v1/webhook_endpoints": {
      "get": {
        "description": "List your webhook endpoints, newest first.\n\nDisabled endpoints are included, so check ``status`` to see which are\nactually receiving events. Deleted ones are not: they are gone.",
        "operationId": "list_webhook_endpoints",
        "parameters": [
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_WebhookEndpointResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Webhook Endpoints",
        "tags": [
          "webhook_endpoints"
        ]
      },
      "post": {
        "description": "Register a URL to receive events.\n\nWebhooks are how you learn that a payment settled, a subscription\nrenewed, or a refund went through. Most of what matters happens\nasynchronously, so an integration that only reads API responses will miss\nit. Register an endpoint before you take your first live payment.\n\nThe signing secret is returned once in this response and never again.\nStore it and use it to verify that an incoming request really came from\nus. ``enabled_events`` lists the event types to send; use ``[\"*\"]`` to\nreceive everything. The URL is checked at creation and a private or\ninternal address is rejected.",
        "operationId": "create_webhook_endpoint",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEndpointCreate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Create Webhook Endpoint",
        "tags": [
          "webhook_endpoints"
        ]
      }
    },
    "/v1/webhook_endpoints/event_types": {
      "get": {
        "description": "Every event type this deployment can deliver.\n\nExists so the answer to \"what may I subscribe to?\" is discoverable rather\nthan folklore. ``enabled_events`` now rejects anything not on this list, so\nwithout a way to read it a caller who guessed wrong would know only that\nthey were wrong \u2014 which is how the six events our own migration guide\npromised went unnoticed for so long.\n\nRead-only and tenant-independent: the catalogue is a property of the\ndeployment, not of the caller's data, so it needs no scope beyond a valid\nkey.",
        "operationId": "list_event_types",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventTypeListResponse"
                }
              }
            },
            "description": "Successful Response"
          }
        },
        "summary": "List Event Types",
        "tags": [
          "webhook_endpoints"
        ]
      }
    },
    "/v1/webhook_endpoints/{endpoint_id}": {
      "delete": {
        "description": "Delete a webhook endpoint.\n\nA wrong URL registered by mistake should not be something you live with\nforever, so this removes it: ``GET /v1/webhook_endpoints/{id}`` returns\n404 afterwards and it is gone from the list. There is no way back, so\nthe response is a deletion marker rather than the endpoint.\n\nIts delivery attempts are removed with it, because they are readable\nonly through this endpoint and nothing could fetch them once it is\ngone. The events themselves are untouched and still in\n``GET /v1/events``, so what you were sent is still on the record.\n\nSend ``status: \"disabled\"`` to ``POST /v1/webhook_endpoints/{id}``\ninstead if you only want delivery to stop. That keeps the endpoint, its\nsigning secret and its history, and you can turn it back on.",
        "operationId": "delete_webhook_endpoint",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeletedResource"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Delete Webhook Endpoint",
        "tags": [
          "webhook_endpoints"
        ]
      },
      "get": {
        "description": "Retrieve one webhook endpoint's configuration.\n\nThe signing secret is not returned; only the fingerprint of it, which is\nenough to tell which secret is current after a rotation. An endpoint\nbelonging to another account returns 404, not 403.",
        "operationId": "get_webhook_endpoint",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Webhook Endpoint",
        "tags": [
          "webhook_endpoints"
        ]
      },
      "post": {
        "description": "Update a webhook endpoint's URL, event list, description or status.\n\nOnly the fields you send change. ``enabled_events`` is replaced\nwholesale, not merged, so send the complete list you want.\n\nSetting ``status`` to ``disabled`` stops delivery while keeping the\nendpoint, its signing secret and its delivery history, which is what\nyou want during planned downtime or while you work out why a receiver\nis failing. Setting it back to ``enabled`` resumes. Use\n``DELETE /v1/webhook_endpoints/{id}`` instead when the endpoint should\nnot exist at all; disabling is reversible and deleting is not.\n\nChanging the URL does not change the signing secret, so your receiver\nkeeps verifying with the same one. Deliveries already queued and not yet\nsent will go to the new URL, so point it somewhere ready to receive them.",
        "operationId": "update_webhook_endpoint",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEndpointUpdate"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Update Webhook Endpoint",
        "tags": [
          "webhook_endpoints"
        ]
      }
    },
    "/v1/webhook_endpoints/{endpoint_id}/deliveries": {
      "get": {
        "description": "List the delivery attempts made to one webhook endpoint, newest first.\n\nThis is where you go when a webhook did not arrive. Each row shows the\nstatus code your receiver returned, an excerpt of its response body, how\nmany attempts have been made, and when the next one is due. It tells you\nwhether the problem is on our side or yours without needing our help.",
        "operationId": "list_webhook_endpoint_deliveries",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 10,
              "maximum": 100,
              "minimum": 1,
              "title": "Limit",
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "starting_after",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "maxLength": 128,
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Starting After"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListResponse_WebhookDeliveryResponse_"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "List Webhook Endpoint Deliveries",
        "tags": [
          "webhook_endpoints"
        ]
      }
    },
    "/v1/webhook_endpoints/{endpoint_id}/deliveries/{delivery_id}": {
      "get": {
        "description": "Retrieve one delivery attempt.\n\nRead the status, response code, body excerpt and error on a single\nattempt before deciding whether to send it again. A delivery belonging to\nanother account, or to a different endpoint, returns 404.",
        "operationId": "get_webhook_delivery",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "delivery_id",
            "required": true,
            "schema": {
              "title": "Delivery Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Get Webhook Delivery",
        "tags": [
          "webhook_endpoints"
        ]
      }
    },
    "/v1/webhook_endpoints/{endpoint_id}/deliveries/{delivery_id}/redeliver": {
      "post": {
        "description": "Send one delivery again, straight away.\n\nUse it after your receiver has been down: bring it back up, then\nredeliver each failed attempt to catch up on what you missed. The event\nis queued for the next send cycle rather than sent inside this request,\nso a 200 here means it is scheduled, not that it arrived.\n\nA delivery that already succeeded is returned unchanged rather than sent\ntwice, so calling this repeatedly is safe. The attempt count is kept\nrather than reset, so the history of what went wrong stays readable.",
        "operationId": "redeliver_webhook_delivery",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "string"
            }
          },
          {
            "in": "path",
            "name": "delivery_id",
            "required": true,
            "schema": {
              "title": "Delivery Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Redeliver Webhook Delivery",
        "tags": [
          "webhook_endpoints"
        ]
      }
    },
    "/v1/webhook_endpoints/{endpoint_id}/rotate_secret": {
      "post": {
        "description": "Replace the endpoint's signing secret.\n\nRotate when a secret may have leaked, or on whatever schedule your own\npolicy sets. The new secret is returned once in this response and never\nagain, so store it before you do anything else.\n\nYou do not have to deploy the new secret instantly. The previous one\nkeeps verifying signatures for 24 hours, so roll it out at your own pace\nwithin that window; after it your receiver must be using the new one.\nRotating again inside the window discards the older secret, so do not\nrotate twice in quick succession.",
        "operationId": "rotate_webhook_endpoint_secret",
        "parameters": [
          {
            "in": "path",
            "name": "endpoint_id",
            "required": true,
            "schema": {
              "title": "Endpoint Id",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResponse"
                }
              }
            },
            "description": "Successful Response"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            },
            "description": "Validation Error"
          }
        },
        "summary": "Rotate Webhook Endpoint Secret",
        "tags": [
          "webhook_endpoints"
        ]
      }
    }
  }
}
