{
  "openapi": "3.1.0",
  "info": {
    "title": "southbill API",
    "version": "2026-01-01",
    "summary": "Accept payments, sell products and run subscriptions with a single REST API.",
    "description": "The southbill REST API. All requests go to `https://api.southbill.com` over HTTPS and are\nauthenticated with an API key. Amounts are integers in the smallest currency unit\n(1000 = 10.00 EUR). All responses are JSON.\n\n**Keys.** Secret keys (`sk_live_…` / `sk_test_…`) are for server-side use and are rejected\nwhen a browser `Origin` header is present. Publishable keys (`pk_live_…` / `pk_test_…`) may\nbe used from the browser but only from an allow-listed domain. Keys carry scopes\n(`checkout:write`, `products:read`, `products:write`, `refunds:write`).\n\n**Test mode.** `*_test_*` keys operate on sandbox data and are logged to Developers → Sandbox.\n\n**Errors.** Every error is `{ \"error\": { \"type\", \"code\", \"param\", \"message\", \"request_id\" } }`.\nThe `request_id` is also returned in the `X-Request-Id` header — log it.\n\n**Rate limits.** Per API key, fixed one-minute windows: 120 checkout creates/min, 300 reads/min,\n60 writes/min (products, subscriptions, refunds). Exceeding a bucket returns `429` with `Retry-After`.\n\n**Idempotency.** Send an `Idempotency-Key` header on create requests to retry safely. Reusing a key\nwith a different payload returns `409 idempotency_error`.",
    "contact": {
      "name": "southbill support",
      "email": "support@southbill.com",
      "url": "https://southbill.com/docs"
    },
    "termsOfService": "https://southbill.com/legal/terms"
  },
  "servers": [
    {
      "url": "https://api.southbill.com",
      "description": "Production (test mode via test keys)"
    }
  ],
  "externalDocs": {
    "description": "southbill documentation",
    "url": "https://southbill.com/docs"
  },
  "tags": [
    {
      "name": "Checkout",
      "description": "Hosted and embedded checkout sessions."
    },
    {
      "name": "Products",
      "description": "Products and prices."
    },
    {
      "name": "Subscriptions",
      "description": "Recurring billing."
    },
    {
      "name": "Refunds",
      "description": "Refunding payments."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    },
    {
      "apiKeyHeader": []
    }
  ],
  "paths": {
    "/v1/checkout/sessions": {
      "post": {
        "tags": [
          "Checkout"
        ],
        "summary": "Create a checkout session",
        "description": "Creates a hosted (or embedded) checkout session. Requires the `checkout:write` scope. Publishable keys and subscription mode must pass `line_items`; secret keys may pass a raw `amount`.",
        "operationId": "createCheckoutSession",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Safely retry a create request. Replaying the same key with the same body returns the original response; reusing it with a different body returns 409 idempotency_error."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckoutSessionCreate"
              },
              "example": {
                "amount": 4900,
                "currency": "eur",
                "customer_name": "Jane Doe",
                "customer_email": "jane@example.com",
                "success_url": "https://example.com/success",
                "cancel_url": "https://example.com/cart",
                "reference": "ORD-1042",
                "metadata": {
                  "order_id": "ORD-1042"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The created checkout session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutSession"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Plan limit reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Fee configuration missing for this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "FX rates or PSP configuration temporarily unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/checkout/sessions/{id}": {
      "get": {
        "tags": [
          "Checkout"
        ],
        "summary": "Retrieve a checkout session",
        "description": "Merchant-authenticated retrieval. The hosted checkout UI uses the same path with `?cs=<client_secret>` and no API key to poll a session it already owns.",
        "operationId": "getCheckoutSession",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cs",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Client secret — allows unauthenticated retrieval from the checkout UI."
          }
        ],
        "responses": {
          "200": {
            "description": "The checkout session.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckoutSession"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "410": {
            "description": "The session has expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/checkout/sessions/{id}/expire": {
      "post": {
        "tags": [
          "Checkout"
        ],
        "summary": "Expire a checkout session",
        "operationId": "expireCheckoutSession",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The expired session.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "example": "expired"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/products": {
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "List products",
        "description": "Requires the `products:read` scope.",
        "operationId": "listProducts",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Cursor: product ID."
          }
        ],
        "responses": {
          "200": {
            "description": "A list of products.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "example": "list"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Create a product",
        "description": "Requires the `products:write` scope. An inline `price` object creates the first price.",
        "operationId": "createProduct",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Safely retry a create request. Replaying the same key with the same body returns the original response; reusing it with a different body returns 409 idempotency_error."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The created product.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Product limit for the current plan reached.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/products/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "Retrieve a product",
        "operationId": "getProduct",
        "responses": {
          "200": {
            "description": "The product, including its prices.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Update a product",
        "operationId": "updateProduct",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated product.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Products"
        ],
        "summary": "Archive a product",
        "operationId": "deleteProduct",
        "responses": {
          "200": {
            "description": "The archived product.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "object": {
                      "type": "string",
                      "example": "product"
                    },
                    "deleted": {
                      "type": "boolean",
                      "example": true
                    },
                    "active": {
                      "type": "boolean",
                      "example": false
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/products/{id}/prices": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Products"
        ],
        "summary": "List prices of a product",
        "operationId": "listPrices",
        "responses": {
          "200": {
            "description": "A list of prices.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "example": "list"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Price"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Create a price",
        "operationId": "createPrice",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Safely retry a create request. Replaying the same key with the same body returns the original response; reusing it with a different body returns 409 idempotency_error."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PriceInput"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The created price.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Price"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/products/{id}/default_price": {
      "post": {
        "tags": [
          "Products"
        ],
        "summary": "Set the default price of a product",
        "operationId": "setDefaultPrice",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "price"
                ],
                "properties": {
                  "price": {
                    "type": "string",
                    "description": "Price ID."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The product with its new default price.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "default_price": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/subscriptions": {
      "get": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "List subscriptions",
        "operationId": "listSubscriptions",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A list of subscriptions.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "type": "string",
                      "example": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Subscription"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "Create a subscription",
        "description": "Requires the `checkout:write` scope and a recurring, active price.",
        "operationId": "createSubscription",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Safely retry a create request. Replaying the same key with the same body returns the original response; reusing it with a different body returns 409 idempotency_error."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "price_id",
                  "customer_email",
                  "customer_name"
                ],
                "properties": {
                  "price_id": {
                    "type": "string",
                    "description": "Recurring price ID (alias: `price`)."
                  },
                  "customer_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "customer_name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "quantity": {
                    "type": "integer",
                    "minimum": 1,
                    "default": 1
                  },
                  "trial_days": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Alias: `trial_period_days`."
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The created subscription, including the client secret for confirmation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Subscription"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/subscriptions/{id}": {
      "get": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "Retrieve a subscription",
        "operationId": "getSubscription",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The subscription.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Subscription"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/subscriptions/{id}/cancel": {
      "post": {
        "tags": [
          "Subscriptions"
        ],
        "summary": "Cancel a subscription",
        "operationId": "cancelSubscription",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "at_period_end": {
                    "type": "boolean",
                    "default": true,
                    "description": "Cancel at the end of the current billing period instead of immediately."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The canceled subscription.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Subscription"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/refunds": {
      "post": {
        "tags": [
          "Refunds"
        ],
        "summary": "Create a refund",
        "description": "Refunds a payment identified by checkout session, charge or payment intent. Requires the `refunds:write` scope. Omit `amount` for a full refund of the remaining balance.",
        "operationId": "createRefund",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Safely retry a create request. Replaying the same key with the same body returns the original response; reusing it with a different body returns 409 idempotency_error."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "description": "Exactly one of `session_id`, `charge_id` or `payment_intent` is required.",
                "properties": {
                  "session_id": {
                    "type": "string"
                  },
                  "charge_id": {
                    "type": "string"
                  },
                  "payment_intent": {
                    "type": "string",
                    "description": "Alias: `payment_intent_id`."
                  },
                  "amount": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Smallest currency unit."
                  },
                  "reason": {
                    "type": "string",
                    "enum": [
                      "duplicate",
                      "fraudulent",
                      "requested_by_customer"
                    ]
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  }
                }
              },
              "example": {
                "session_id": "cs_live_123",
                "amount": 1000,
                "reason": "requested_by_customer"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The created refund.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Refund"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request — a parameter is missing or malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, revoked or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key exists but lacks the required scope, or the origin is not allow-listed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found or not owned by this merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "405": {
            "description": "Only POST is supported on this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting state (idempotency key reused, already refunded, disputed, wrong state).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected API error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "The payment processor rejected the refund.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "`Authorization: Bearer sk_live_…`. Secret keys are server-side only; publishable keys (`pk_live_…`) are accepted from allow-listed browser origins."
      },
      "apiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Southbill-Api-Key",
        "description": "Alternative to the Authorization header."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "type",
              "message",
              "request_id"
            ],
            "properties": {
              "type": {
                "type": "string",
                "description": "Error family.",
                "enum": [
                  "invalid_request",
                  "authentication_error",
                  "permission_error",
                  "not_found",
                  "idempotency_error",
                  "rate_limit_error",
                  "api_error"
                ]
              },
              "code": {
                "type": "string",
                "examples": [
                  "amount_too_small",
                  "already_refunded",
                  "charge_disputed"
                ]
              },
              "param": {
                "type": "string",
                "description": "The offending request field, when applicable."
              },
              "message": {
                "type": "string"
              },
              "request_id": {
                "type": "string",
                "description": "Unique id for this request, also returned in the `X-Request-Id` header. Log it and quote it in support requests."
              }
            }
          }
        }
      },
      "Address": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "line1": {
            "type": "string"
          },
          "line2": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "postal_code": {
            "type": "string"
          },
          "country": {
            "type": "string",
            "description": "Two-letter ISO country code."
          },
          "phone": {
            "type": "string"
          }
        }
      },
      "CheckoutSessionCreate": {
        "type": "object",
        "description": "A payment-mode session must carry either `amount` + `currency` (secret keys only) or `line_items` / `price_id`. A subscription-mode session must carry `line_items` (or `price_id`) referencing a recurring price. Publishable keys must always use `line_items` / `price_id`.",
        "required": [
          "customer_name",
          "customer_email"
        ],
        "oneOf": [
          {
            "title": "Amount-based (payment mode, secret keys)",
            "required": [
              "amount",
              "currency"
            ],
            "properties": {
              "mode": {
                "const": "payment"
              }
            }
          },
          {
            "title": "Price-based (payment or subscription mode)",
            "anyOf": [
              {
                "required": [
                  "line_items"
                ]
              },
              {
                "required": [
                  "price_id"
                ]
              }
            ]
          }
        ],
        "properties": {
          "mode": {
            "type": "string",
            "enum": [
              "payment",
              "subscription"
            ],
            "default": "payment"
          },
          "amount": {
            "type": "integer",
            "description": "Smallest currency unit. Payment mode only, secret keys only. Alias: `amount_cents`."
          },
          "currency": {
            "type": "string",
            "description": "Three-letter ISO code, lowercase.",
            "example": "eur"
          },
          "customer_name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 120
          },
          "customer_email": {
            "type": "string",
            "format": "email"
          },
          "customer_phone": {
            "type": "string",
            "maxLength": 40
          },
          "billing_address": {
            "$ref": "#/components/schemas/Address"
          },
          "shipping_address": {
            "$ref": "#/components/schemas/Address"
          },
          "line_items": {
            "type": "array",
            "minItems": 1,
            "description": "Required for publishable keys and for subscription mode. In subscription mode every price must be recurring; in payment mode none may be recurring, and all items must share one currency.",
            "items": {
              "type": "object",
              "required": [
                "price"
              ],
              "properties": {
                "price": {
                  "type": "string",
                  "description": "Price ID (`price_…`) owned by this merchant."
                },
                "quantity": {
                  "type": "integer",
                  "minimum": 1,
                  "default": 1
                }
              }
            }
          },
          "price_id": {
            "type": "string",
            "description": "Shorthand for a single line item."
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "default": 1,
            "description": "Used together with `price_id`."
          },
          "reference": {
            "type": "string",
            "description": "Your own order reference."
          },
          "description": {
            "type": "string"
          },
          "success_url": {
            "type": "string",
            "format": "uri"
          },
          "cancel_url": {
            "type": "string",
            "format": "uri"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "integration": {
            "type": "object",
            "description": "Optional plugin integration callback.",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "woocommerce",
                  "prestashop"
                ]
              },
              "webhook_url": {
                "type": "string",
                "format": "uri"
              },
              "webhook_secret": {
                "type": "string",
                "description": "Starts with `whsec_`."
              }
            }
          }
        }
      },
      "CheckoutSession": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "example": "checkout.session"
          },
          "mode": {
            "type": "string",
            "enum": [
              "payment",
              "subscription"
            ],
            "description": "Checkout type — never the environment."
          },
          "livemode": {
            "type": "boolean",
            "description": "`false` for sessions created with a test key."
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "complete",
              "expired"
            ]
          },
          "amount": {
            "type": "integer"
          },
          "currency": {
            "type": "string",
            "description": "Three-letter ISO code, lowercase."
          },
          "reference": {
            "type": "string",
            "nullable": true
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "customer_email": {
            "type": "string",
            "format": "email",
            "nullable": true
          },
          "customer_name": {
            "type": "string",
            "nullable": true
          },
          "client_secret": {
            "type": "string",
            "description": "Needed by the embedded checkout UI."
          },
          "checkout_url": {
            "type": "string",
            "format": "uri",
            "description": "Redirect your customer here."
          },
          "embed_url": {
            "type": "string",
            "format": "uri"
          },
          "success_url": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "cancel_url": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "line_items": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "payment_intent": {
            "type": "string",
            "nullable": true
          },
          "setup_intent": {
            "type": "string",
            "nullable": true
          },
          "subscription": {
            "type": "string",
            "nullable": true
          },
          "intent_type": {
            "type": "string",
            "enum": [
              "payment",
              "setup"
            ],
            "nullable": true
          },
          "charge": {
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "expires_at": {
            "type": "integer",
            "description": "Unix timestamp."
          },
          "completed_at": {
            "type": "integer",
            "nullable": true
          },
          "created": {
            "type": "integer",
            "description": "Unix timestamp."
          }
        }
      },
      "ProductInput": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "images": {
            "type": "array",
            "maxItems": 8,
            "items": {
              "type": "string",
              "format": "uri"
            }
          },
          "active": {
            "type": "boolean",
            "default": true
          },
          "tax_code": {
            "type": "string"
          },
          "unit_label": {
            "type": "string",
            "maxLength": 12
          },
          "statement_descriptor": {
            "type": "string",
            "maxLength": 22
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "shippable": {
            "type": "boolean"
          },
          "package_dimensions": {
            "type": "object",
            "properties": {
              "length": {
                "type": "number"
              },
              "width": {
                "type": "number"
              },
              "height": {
                "type": "number"
              },
              "weight": {
                "type": "number"
              }
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "price": {
            "$ref": "#/components/schemas/PriceInput"
          }
        }
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "example": "product"
          },
          "livemode": {
            "type": "boolean",
            "description": "`false` for objects created with a test key."
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "images": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "active": {
            "type": "boolean"
          },
          "tax_code": {
            "type": "string",
            "nullable": true
          },
          "unit_label": {
            "type": "string",
            "nullable": true
          },
          "statement_descriptor": {
            "type": "string",
            "nullable": true
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "shippable": {
            "type": "boolean",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "default_price": {
            "type": "string",
            "nullable": true
          },
          "prices": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Price"
            }
          },
          "created": {
            "type": "integer",
            "description": "Unix timestamp."
          }
        }
      },
      "PriceInput": {
        "type": "object",
        "required": [
          "currency"
        ],
        "properties": {
          "currency": {
            "type": "string",
            "example": "eur"
          },
          "unit_amount": {
            "type": "integer",
            "minimum": 250,
            "description": "Smallest currency unit."
          },
          "custom_unit_amount": {
            "type": "object",
            "properties": {
              "minimum": {
                "type": "integer"
              },
              "maximum": {
                "type": "integer"
              },
              "preset": {
                "type": "integer"
              }
            }
          },
          "tiers": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "tiers_mode": {
            "type": "string",
            "enum": [
              "graduated",
              "volume"
            ]
          },
          "billing_scheme": {
            "type": "string",
            "enum": [
              "per_unit",
              "tiered"
            ]
          },
          "tax_behavior": {
            "type": "string",
            "enum": [
              "inclusive",
              "exclusive",
              "unspecified"
            ]
          },
          "nickname": {
            "type": "string"
          },
          "lookup_key": {
            "type": "string"
          },
          "recurring": {
            "type": "object",
            "properties": {
              "interval": {
                "type": "string",
                "enum": [
                  "day",
                  "week",
                  "month",
                  "year"
                ]
              },
              "interval_count": {
                "type": "integer",
                "minimum": 1
              },
              "usage_type": {
                "type": "string",
                "enum": [
                  "licensed",
                  "metered"
                ]
              },
              "aggregate_usage": {
                "type": "string"
              },
              "trial_period_days": {
                "type": "integer"
              }
            }
          },
          "set_as_default": {
            "type": "boolean"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "Price": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "example": "price"
          },
          "livemode": {
            "type": "boolean",
            "description": "`false` for objects created with a test key."
          },
          "product": {
            "type": "string"
          },
          "currency": {
            "type": "string",
            "description": "Lowercase ISO code.",
            "example": "eur"
          },
          "unit_amount": {
            "type": "integer",
            "nullable": true
          },
          "nickname": {
            "type": "string",
            "nullable": true
          },
          "billing_scheme": {
            "type": "string"
          },
          "tax_behavior": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "one_time",
              "recurring"
            ]
          },
          "recurring": {
            "type": "object",
            "nullable": true,
            "properties": {
              "interval": {
                "type": "string"
              },
              "interval_count": {
                "type": "integer"
              },
              "usage_type": {
                "type": "string"
              },
              "aggregate_usage": {
                "type": "string",
                "nullable": true
              },
              "trial_period_days": {
                "type": "integer",
                "nullable": true
              }
            }
          },
          "lookup_key": {
            "type": "string",
            "nullable": true
          },
          "custom_unit_amount": {
            "type": "object",
            "nullable": true
          },
          "transform_quantity": {
            "type": "object",
            "nullable": true
          },
          "tiers_mode": {
            "type": "string",
            "nullable": true
          },
          "tiers": {
            "type": "array",
            "nullable": true,
            "items": {
              "type": "object"
            }
          },
          "active": {
            "type": "boolean"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "created": {
            "type": "integer"
          }
        }
      },
      "Subscription": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "example": "subscription"
          },
          "livemode": {
            "type": "boolean",
            "description": "`false` for objects created with a test key."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "past_due",
              "canceled",
              "incomplete",
              "incomplete_expired",
              "trialing",
              "unpaid"
            ]
          },
          "customer": {
            "type": "string"
          },
          "price_id": {
            "type": "string"
          },
          "quantity": {
            "type": "integer"
          },
          "amount": {
            "type": "integer"
          },
          "currency": {
            "type": "string",
            "description": "Lowercase ISO code.",
            "example": "eur"
          },
          "application_fee_percent": {
            "type": "number",
            "nullable": true
          },
          "latest_invoice": {
            "type": "string",
            "nullable": true
          },
          "client_secret": {
            "type": "string",
            "nullable": true,
            "description": "Confirm the first payment or setup with this."
          },
          "intent_type": {
            "type": "string",
            "enum": [
              "payment",
              "setup"
            ],
            "nullable": true
          },
          "payment_intent": {
            "type": "string",
            "nullable": true
          },
          "setup_intent": {
            "type": "string",
            "nullable": true
          },
          "trial_end": {
            "type": "integer",
            "nullable": true
          },
          "current_period_end": {
            "type": "integer",
            "nullable": true
          },
          "cancel_at_period_end": {
            "type": "boolean"
          },
          "canceled_at": {
            "type": "integer",
            "nullable": true
          },
          "created": {
            "type": "integer"
          }
        }
      },
      "Refund": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "object": {
            "type": "string",
            "example": "refund"
          },
          "livemode": {
            "type": "boolean",
            "description": "`false` for objects created with a test key."
          },
          "charge": {
            "type": "string"
          },
          "payment_intent": {
            "type": "string",
            "nullable": true
          },
          "amount": {
            "type": "integer"
          },
          "currency": {
            "type": "string",
            "description": "Lowercase ISO code.",
            "example": "eur"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "succeeded",
              "failed",
              "canceled"
            ]
          },
          "reason": {
            "type": "string",
            "nullable": true
          },
          "created": {
            "type": "integer"
          }
        }
      }
    }
  }
}