{
  "openapi": "3.1.1",
  "info": {
    "title": "Runa API",
    "version": "2024-02-05",
    "description": "Runa is the infrastructure and network for global payouts – gift cards, prepaid cards, and push-to-card – all managed from a single, unified platform.\n\nUse this API to browse the product catalog, place and track payout orders, manage your account balances, and receive webhooks when orders complete or product availability changes.\n\nGuides, tutorials and the changelog are on the [Runa developer hub](https://developer.runa.io).",
    "termsOfService": "https://runa.io/terms-of-use",
    "contact": {
      "name": "Runa",
      "url": "https://runa.io",
      "email": "info@runa.io"
    }
  },
  "externalDocs": {
    "url": "https://developer.runa.io/reference",
    "description": "Runa API Reference"
  },
  "servers": [
    {
      "url": "https://playground.runa.io/v2",
      "description": "Playground"
    },
    {
      "url": "https://api.runa.io/v2",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "Utility",
      "description": "Utility endpoints."
    },
    {
      "name": "Balance",
      "description": "Operations related to account balance."
    },
    {
      "name": "Products",
      "description": "Operations related to products."
    },
    {
      "name": "Orders",
      "description": "Operations related to ordering and orders."
    }
  ],
  "paths": {
    "/ping": {
      "get": {
        "operationId": "ping",
        "tags": ["Utility"],
        "summary": "Ping endpoint",
        "description": "Check your integration can connect to the Runa API\n\n**Required scope:** `read:ping`",
        "security": [{ "ApiKeyAuth": ["read:ping"] }],
        "parameters": [{ "$ref": "#/components/parameters/X-Api-Version" }],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string",
                      "const": "pong"
                    }
                  },
                  "required": ["message"]
                },
                "example": {
                  "message": "pong"
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/InternalServerError" }
        }
      }
    },
    "/balance": {
      "get": {
        "operationId": "getBalance",
        "tags": ["Balance"],
        "summary": "Get account balance",
        "description": "Retrieves the account balance. Returns the balance in a specified currency if the currency parameter is provided. If not, returns all balances greater than 0.\n\n**Required scope:** `read:balance`",
        "security": [{ "ApiKeyAuth": ["read:balance"] }],
        "parameters": [
          { "$ref": "#/components/parameters/X-Api-Version" },
          { "$ref": "#/components/parameters/CurrencyForAccount" }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "title": "Single balance",
                      "description": "If the `currency` parameter is provided, the response will be a single balance object.",
                      "type": "object",
                      "properties": {
                        "balance": {
                          "$ref": "#/components/schemas/MonetaryAmount",
                          "description": "The balance of the account.",
                          "examples": ["10.00"]
                        },
                        "currency": {
                          "$ref": "#/components/schemas/Currency"
                        }
                      }
                    },
                    {
                      "title": "Multiple balances",
                      "description": "If the `currency` parameter is omitted, the response will be an array of balance objects.",
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "balance": {
                            "$ref": "#/components/schemas/MonetaryAmount",
                            "description": "The balance of the account.",
                            "examples": ["10.00"]
                          },
                          "currency": {
                            "$ref": "#/components/schemas/Currency"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "Single Balance": {
                    "summary": "Single balance",
                    "value": {
                      "balance": "10.00",
                      "currency": "USD"
                    }
                  },
                  "Multiple Balances": {
                    "summary": "Multiple balances",
                    "value": [
                      { "balance": "10.00", "currency": "USD" },
                      { "balance": "8.50", "currency": "GBP" }
                    ]
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/InternalServerError" }
        }
      }
    },
    "/order": {
      "get": {
        "operationId": "listOrders",
        "tags": ["Orders"],
        "summary": "List orders",
        "description": "Get a list of all of your orders\n\n**Required scope:** `read:order`",
        "security": [{ "ApiKeyAuth": ["read:order"] }],
        "parameters": [
          { "$ref": "#/components/parameters/X-Api-Version" },
          {
            "required": false,
            "name": "limit",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            },
            "in": "query",
            "description": "Number of orders per page, 1 to 500."
          },
          { "$ref": "#/components/parameters/BeforeCursor" },
          { "$ref": "#/components/parameters/AfterCursor" }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["items", "pagination"],
                  "properties": {
                    "items": {
                      "title": "Items",
                      "description": "The list of orders in the page.",
                      "type": "array",
                      "items": {
                        "oneOf": [
                          {
                            "$ref": "#/components/schemas/OrderSummary"
                          },
                          {
                            "$ref": "#/components/schemas/ProcessingOrder"
                          }
                        ],
                        "discriminator": {
                          "propertyName": "status",
                          "mapping": {
                            "COMPLETED": "#/components/schemas/OrderSummary",
                            "FAILED": "#/components/schemas/OrderSummary",
                            "PROCESSING": "#/components/schemas/ProcessingOrder"
                          }
                        }
                      }
                    },
                    "pagination": {
                      "title": "Pagination",
                      "description": "Metadata of the result page.",
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/InternalServerError" }
        }
      },
      "post": {
        "operationId": "createOrder",
        "tags": ["Orders"],
        "summary": "Create a new order.",
        "description": "Creates a new order.\n\n**Required scope:** `create:order`",
        "security": [{ "ApiKeyAuth": ["create:order"] }],
        "parameters": [
          { "$ref": "#/components/parameters/X-Api-Version" },
          {
            "required": true,
            "name": "X-Idempotency-Key",
            "schema": {
              "type": "string"
            },
            "in": "header",
            "description": "A unique string that prevents order duplication. See [Idempotency](/best-practices/idempotency) for more information."
          },
          {
            "name": "X-Execution-Mode",
            "schema": {
              "type": "string",
              "enum": ["async", "sync"],
              "default": "async"
            },
            "in": "header",
            "description": "Whether to process the order synchronously or asynchronously. If this header is omitted we default to async. See [which mode to use](/getting-started/first-order/which-mode) to help you decide which execution mode is right for your use case. Sync orders are limited to a single order item.",
            "example": "async"
          }
        ],
        "responses": {
          "200": {
            "description": "Response that will be returned in sync execution mode. Order has successfully been completed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderCreationResult"
                }
              }
            }
          },
          "202": {
            "description": "Response that will be returned in async execution mode. Order has successfully been accepted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderCreationResult"
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/ValidationError" },
          "429": { "$ref": "#/components/responses/RateExceeded" },
          "500": { "$ref": "#/components/responses/InternalServerError" }
        },
        "requestBody": {
          "required": true,
          "description": "The details of the order to create.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOrderRequest"
              }
            }
          }
        }
      }
    },
    "/order/{id}": {
      "get": {
        "operationId": "getOrder",
        "tags": ["Orders"],
        "summary": "Get order details",
        "description": "Get the details and status of a specific order. Can be used for checking the status of an async order after it's been accepted.\n\n**Required scope:** `read:order`",
        "security": [{ "ApiKeyAuth": ["read:order"] }],
        "parameters": [
          { "$ref": "#/components/parameters/X-Api-Version" },
          {
            "required": true,
            "name": "id",
            "schema": {
              "type": "string"
            },
            "in": "path",
            "description": "The ID of the order.",
            "example": "O-01H5WQGHKCBB85MQFM68S9KJ5Q"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Order"
                    },
                    {
                      "$ref": "#/components/schemas/ProcessingOrder"
                    }
                  ],
                  "discriminator": {
                    "propertyName": "status",
                    "mapping": {
                      "COMPLETED": "#/components/schemas/Order",
                      "FAILED": "#/components/schemas/Order",
                      "PROCESSING": "#/components/schemas/ProcessingOrder"
                    }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "500": { "$ref": "#/components/responses/InternalServerError" }
        }
      }
    },
    "/order/estimate": {
      "post": {
        "operationId": "estimateOrder",
        "tags": ["Orders"],
        "summary": "Estimate order",
        "description": "Estimate price for the order.\n\n**Required scope:** `read:order`",
        "security": [{ "ApiKeyAuth": ["read:order"] }],
        "parameters": [{ "$ref": "#/components/parameters/X-Api-Version" }],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderEstimateResponse"
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "422": { "$ref": "#/components/responses/ValidationError" },
          "500": { "$ref": "#/components/responses/InternalServerError" }
        },
        "requestBody": {
          "required": true,
          "description": "The details of the order to estimate.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OrderEstimateRequest"
              }
            }
          }
        }
      }
    },
    "/order-item/{order_item_id}/fulfilment": {
      "post": {
        "operationId": "createFulfilment",
        "tags": ["Orders"],
        "summary": "Fulfil an order item",
        "description": "Issue the gift card for an order item and return its redemption details, so you can present them in your own experience.\n\nThe call is synchronous and idempotent: calling it again for the same order item returns the card already issued and never issues a second one, so it's safe to retry after a timeout.\n\nThe order item must belong to your account, be part of a completed order and hold a single gift card product. Payment products and multi-product payouts can't be fulfilled through this endpoint; their recipients redeem them through the payout link.\n\nThis endpoint isn't enabled by default. To enable it, contact your Account Manager.\n\n**Required scope:** `create:fulfilment`",
        "security": [{ "ApiKeyAuth": ["create:fulfilment"] }],
        "servers": [
          { "url": "https://api.runa.io/v2", "description": "Production" }
        ],
        "parameters": [
          { "$ref": "#/components/parameters/X-Api-Version" },
          {
            "required": true,
            "name": "order_item_id",
            "schema": { "type": "string", "pattern": "^E-[0-9A-Z]+$" },
            "in": "path",
            "description": "The ID of the order item, as returned in `items[].id` when you create or get an order.",
            "example": "E-01P2K5GWRECHT908FY184ZZ9VG"
          }
        ],
        "responses": {
          "200": {
            "description": "The gift card's redemption details.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FulfilmentDetails" },
                "examples": {
                  "code": {
                    "summary": "Card redeemed with a code",
                    "value": {
                      "code": "6280399992147003",
                      "pin": "25468113",
                      "expiry_date": "2029-04-16",
                      "barcode": {
                        "format": "QR",
                        "value": "6280399992147003"
                      },
                      "url": null
                    }
                  },
                  "url": {
                    "summary": "Card redeemed by URL",
                    "value": {
                      "code": null,
                      "pin": null,
                      "expiry_date": null,
                      "barcode": null,
                      "url": "https://redeem.example.com/r/ABCD-EFGH-IJKL"
                    }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": {
            "description": "The API key doesn't have the `create:fulfilment` scope, or your account isn't enabled for the Fulfilment API.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponse" },
                "examples": {
                  "missing_scope": {
                    "summary": "API key without the create:fulfilment scope",
                    "value": {
                      "type": "forbidden",
                      "message": "You don't have permission to access the requested resource",
                      "help": "Please check the path you are trying to access is correct and you have permission to access it. Also ensure you are using the correct API key in the 'X-Api-Key' header."
                    }
                  },
                  "not_enabled": {
                    "summary": "Account not enabled for the Fulfilment API",
                    "value": {
                      "type": "forbidden",
                      "message": "The account is not enabled for fulfilment"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No order item with this ID exists on your account, or the order item has been cancelled.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponse" },
                "examples": {
                  "not_found": {
                    "value": {
                      "type": "not_found",
                      "message": "Order item not found"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "The payout can't be fulfilled in its current state.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponse" },
                "examples": {
                  "payout_expired": {
                    "value": {
                      "type": "payout_expired",
                      "message": "The payout has expired",
                      "help": "Place a new order."
                    }
                  },
                  "payout_cancelled": {
                    "value": {
                      "type": "payout_cancelled",
                      "message": "The payout has been cancelled"
                    }
                  },
                  "product_not_active": {
                    "value": {
                      "type": "product_not_active",
                      "message": "The product is no longer active"
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "The order item can't be fulfilled through the API. Payment products and multi-product payouts are redeemed through the payout link.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponse" },
                "examples": {
                  "unsupported": {
                    "value": {
                      "type": "unsupported",
                      "message": "This payout cannot be fulfilled through the API",
                      "help": "The recipient can redeem it through the payout link."
                    }
                  }
                }
              }
            }
          },
          "424": {
            "description": "The provider couldn't issue the card. Retry in a few minutes.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponse" },
                "examples": {
                  "provider_fulfilment_error": {
                    "value": {
                      "type": "provider_fulfilment_error",
                      "message": "The provider could not issue the card",
                      "help": "Retry in a few minutes."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "Another request for the same order item is in progress, or the API key exceeded its rate limit of 20 requests every 10 seconds. Retry after the number of seconds in the `Retry-After` header when it's present; otherwise wait 10 seconds before retrying.",
            "headers": {
              "Retry-After": {
                "description": "Seconds to wait before retrying. Only sent when another request for the same order item is in progress.",
                "schema": { "type": "integer" }
              }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponse" },
                "examples": {
                  "rate_limit": {
                    "summary": "Another request for the order item is in progress",
                    "value": {
                      "type": "rate_limit",
                      "message": "Too many requests",
                      "help": "Retry after the number of seconds in the Retry-After header."
                    }
                  },
                  "throttled": {
                    "summary": "More than 20 requests in 10 seconds with the same API key",
                    "value": {
                      "type": "rate_limit",
                      "message": "You've exceeded the rate limit, please wait 10 seconds and try again.",
                      "help": "See https://developer.runa.io/rate-limits for details."
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "The card couldn't be issued. Retry the same call: if the card was issued in the meantime, it's returned.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponse" },
                "examples": {
                  "internal_server_error": {
                    "value": {
                      "type": "internal_server_error",
                      "message": "The card could not be issued",
                      "help": "Retry later, or contact ordersupport@runa.io."
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "An unexpected error occurred. Retry the same call.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponse" },
                "example": {
                  "type": "internal_server_error",
                  "message": "An internal server error occurred",
                  "help": "Please try again, or contact ordersupport@runa.io for assistance."
                }
              }
            }
          },
          "504": {
            "description": "The request timed out. The card may still be issued: retry the same call to get it.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ApiErrorResponse" },
                "example": {
                  "type": "timeout",
                  "message": "The request timed out",
                  "help": "We were unable to process your request in time. This is a temporary issue, please try again. If the problem persists please contact ordersupport@runa.io"
                }
              }
            }
          }
        }
      }
    },
    "/product": {
      "get": {
        "operationId": "listProducts",
        "summary": "List products",
        "description": "List all products in your catalog\n\n**Required scope:** `read:product`",
        "security": [{ "ApiKeyAuth": ["read:product"] }],
        "tags": ["Products"],
        "parameters": [
          { "$ref": "#/components/parameters/X-Api-Version" },
          {
            "in": "query",
            "name": "is_orderable",
            "description": "Filter by whether a product can be ordered. If `true`, only orderable products are returned. If `false` or omitted, both orderable and non-orderable products are returned.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "in": "query",
            "name": "countries_redeemable_in",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "pattern": "^[A-Z]{2}$",
                "description": "ISO 3166 ALPHA-2 country code"
              }
            },
            "description": "Filter by countries where a product can be redeemed in. To specify multiple countries repeat the parameter for each country, e.g. `?countries_redeemable_in=US&countries_redeemable_in=GB`. You can pull the list of supported countries from the [list countries](/reference/2024-02-05/endpoint/products/countries) endpoint."
          },
          {
            "in": "query",
            "name": "categories",
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "description": "Product category name"
              }
            },
            "description": "Filter by product categories. To specify multiple categories repeat the parameter for each category, e.g. `?categories=fashion&categories=department-stores`. You can pull the list of categories from the [list categories](/reference/2024-02-05/endpoint/products/categories) endpoint."
          },
          { "$ref": "#/components/parameters/BeforeCursor" },
          { "$ref": "#/components/parameters/AfterCursor" },
          {
            "in": "query",
            "name": "limit",
            "description": "A limit on the number of items to be returned. See [pagination](/reference/pagination) for more information on how to use this parameter.",
            "schema": {
              "type": "integer",
              "default": 500,
              "minimum": 1,
              "maximum": 500
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of products in your catalog",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "catalog": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/InternalServerError" }
        }
      }
    },
    "/product/{product_code}": {
      "get": {
        "operationId": "getProduct",
        "tags": ["Products"],
        "summary": "Get product details",
        "description": "Retrieve a single product's details\n\n**Required scope:** `read:product`",
        "security": [{ "ApiKeyAuth": ["read:product"] }],
        "parameters": [
          { "$ref": "#/components/parameters/X-Api-Version" },
          {
            "required": true,
            "name": "product_code",
            "schema": {
              "type": "string"
            },
            "in": "path",
            "description": "The code of the product."
          },
          {
            "name": "content",
            "in": "query",
            "required": false,
            "description": "Defines the format for product content resources.\n\n- `url` _(default)_ for external URLs to markdown content\n- `md` for Markdown content in the response\n- `html` for rendered HTML in the response",
            "schema": {
              "type": "string",
              "enum": ["url", "md", "html"],
              "default": "url"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "404": { "$ref": "#/components/responses/NotFound" },
          "500": { "$ref": "#/components/responses/InternalServerError" }
        }
      }
    },
    "/product/countries": {
      "get": {
        "operationId": "listProductCountries",
        "tags": ["Products"],
        "summary": "List countries",
        "description": "Get a list of countries where products are available\n\n**Required scope:** `read:product`",
        "security": [{ "ApiKeyAuth": ["read:product"] }],
        "parameters": [{ "$ref": "#/components/parameters/X-Api-Version" }],
        "responses": {
          "200": {
            "description": "A list of countries where products are available",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "countries": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "pattern": "^[A-Z]{2}$",
                        "description": "ISO 3166 ALPHA-2 country code"
                      },
                      "examples": [
                        [
                          "AT",
                          "AU",
                          "BE",
                          "CA",
                          "CH",
                          "CZ",
                          "DE",
                          "DK",
                          "ES",
                          "FI",
                          "FR",
                          "GB",
                          "GR",
                          "HU",
                          "IE",
                          "IT",
                          "JP",
                          "LU",
                          "MX",
                          "NL",
                          "NO",
                          "NZ",
                          "PL",
                          "PT",
                          "RO",
                          "SE",
                          "SG",
                          "SI",
                          "US",
                          "ZA"
                        ]
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/InternalServerError" }
        }
      }
    },
    "/product/categories": {
      "get": {
        "operationId": "listProductCategories",
        "tags": ["Products"],
        "summary": "List categories",
        "description": "Get a list of all possible product categories\n\n**Required scope:** `read:product`",
        "security": [{ "ApiKeyAuth": ["read:product"] }],
        "parameters": [{ "$ref": "#/components/parameters/X-Api-Version" }],
        "responses": {
          "200": {
            "description": "A list of all possible product categories",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "categories": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "code": {
                            "type": "string"
                          }
                        },
                        "required": ["code"]
                      },
                      "examples": [
                        [
                          { "code": "beauty-and-lifestyle" },
                          { "code": "booksellers" },
                          { "code": "department-stores" },
                          { "code": "electricals" },
                          { "code": "entertainment" },
                          { "code": "experiences" },
                          { "code": "fashion" },
                          { "code": "food-and-drink" },
                          { "code": "home-and-diy" },
                          { "code": "jewellers" },
                          { "code": "leisure-and-sports" },
                          { "code": "mens-fashion" },
                          { "code": "prepaid-card" },
                          { "code": "supermarkets" },
                          { "code": "toys-and-games" },
                          { "code": "travel" },
                          { "code": "womens-fashion" }
                        ]
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": { "$ref": "#/components/responses/BadRequest" },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "403": { "$ref": "#/components/responses/Forbidden" },
          "500": { "$ref": "#/components/responses/InternalServerError" }
        }
      }
    }
  },
  "webhooks": {
    "order.completion": {
      "post": {
        "summary": "Order completion",
        "operationId": "orderCompletionWebhook",
        "description": "Sent to your configured endpoint when an order finishes processing, whether it completed or failed. See [webhooks](/reference/webhooks) for how to configure and verify them.",
        "security": [],
        "requestBody": {
          "description": "Sent when an order finishes processing, the body object will be one of the following schemas depending on the order status.",
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  { "$ref": "#/components/schemas/CompletedOrderWebhook" },
                  { "$ref": "#/components/schemas/FailedOrderWebhook" }
                ],
                "discriminator": {
                  "propertyName": "status",
                  "mapping": {
                    "COMPLETED": "#/components/schemas/CompletedOrderWebhook",
                    "FAILED": "#/components/schemas/FailedOrderWebhook"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return a 200 status to indicate that the data was received successfully"
          }
        }
      }
    },
    "product.update": {
      "post": {
        "summary": "Product update",
        "operationId": "productUpdateWebhook",
        "description": "Sent to your configured endpoint when a product's orderability or discount changes. See [webhooks](/reference/webhooks) for how to configure and verify them.",
        "security": [],
        "requestBody": {
          "description": "Update on product status",
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ProductUpdateWebhook" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return a 200 status to indicate that the data was received successfully"
          }
        }
      }
    }
  },
  "components": {
    "parameters": {
      "X-Api-Version": {
        "name": "X-Api-Version",
        "description": "The dated version of the API, if not specified a default is used. See [API versioning](/best-practices/api-versioning) for more information.",
        "in": "header",
        "required": false,
        "schema": {
          "$ref": "#/components/schemas/ApiVersion"
        }
      },
      "CurrencyForAccount": {
        "name": "currency",
        "required": false,
        "schema": {
          "$ref": "#/components/schemas/Currency"
        },
        "description": "The currency of the account, represented by ISO 4217 currency codes. Check the [currencies](/reference/currencies) for a listing of supported currencies.",
        "in": "query",
        "example": "USD"
      },
      "BeforeCursor": {
        "name": "before",
        "description": "A cursor for use in pagination to return the previous set of results. The before and after cursors are mutually exclusive (you can't use them at the same time). You can get a value from the `pagination.cursors.before` field in the response. See [pagination](/reference/pagination) for more information.",
        "in": "query",
        "schema": {
          "type": "string",
          "examples": ["A-123"]
        }
      },
      "AfterCursor": {
        "name": "after",
        "description": "A cursor for use in pagination to return the next set of results. The before and after cursors are mutually exclusive (you can't use them at the same time). You can get a value from the `pagination.cursors.after` field in the response. See [pagination](/reference/pagination) for more information.",
        "in": "query",
        "schema": {
          "type": "string",
          "examples": ["A-789"]
        }
      }
    },
    "schemas": {
      "FulfilmentDetails": {
        "title": "Fulfilment details",
        "type": "object",
        "required": ["code", "pin", "expiry_date", "barcode", "url"],
        "properties": {
          "code": {
            "type": ["string", "null"],
            "description": "The gift card code, exactly as issued, or `null` for cards redeemed online: use `url` for those.",
            "examples": ["6280399992147003"]
          },
          "pin": {
            "type": ["string", "null"],
            "description": "The PIN or security code, when the card has one.",
            "examples": ["25468113"]
          },
          "expiry_date": {
            "type": ["string", "null"],
            "format": "date",
            "description": "The last day the card can be used, as `YYYY-MM-DD`, or `null` if it doesn't expire.",
            "examples": ["2029-04-16"]
          },
          "barcode": {
            "oneOf": [
              { "$ref": "#/components/schemas/FulfilmentBarcode" },
              { "type": "null" }
            ],
            "description": "The barcode to present in store, when the card has one."
          },
          "url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "The URL where the card is redeemed, when it's redeemed online.",
            "examples": ["https://redeem.example.com/r/ABCD-EFGH-IJKL"]
          }
        },
        "description": "A gift card's redemption details. Fields that don't apply to the card are `null`. Display whichever of `code`, `pin` and `barcode` are present, or send the recipient to `url`."
      },
      "FulfilmentBarcode": {
        "title": "Fulfilment barcode",
        "type": "object",
        "required": ["format", "value"],
        "properties": {
          "format": {
            "type": "string",
            "description": "The barcode symbology, for example `QR` or `CODE_128`.",
            "examples": ["QR"]
          },
          "value": {
            "type": "string",
            "description": "The value to encode in the barcode.",
            "examples": ["6280399992147003"]
          }
        }
      },
      "ApiErrorResponse": {
        "title": "Error",
        "required": ["type", "message"],
        "type": "object",
        "properties": {
          "type": {
            "title": "Type",
            "description": "An error code or type.",
            "type": "string",
            "examples": ["not_found"]
          },
          "message": {
            "title": "Message",
            "description": "A human readable summary of the error.",
            "type": "string",
            "examples": ["The requested resource was not found"]
          },
          "help": {
            "title": "Help",
            "description": "Additional information that pertains to the error. `null` when there is nothing further to add.",
            "type": ["string", "null"],
            "examples": ["Please check the resource ID and try again."]
          }
        },
        "description": "Generic Runa API error response."
      },
      "ApiVersion": {
        "title": "API version",
        "type": "string",
        "enum": ["2024-02-05"],
        "default": "2024-02-05",
        "description": "The dated version of the Runa API. Send it on every request: a client that omits it silently follows whatever the server default happens to be."
      },
      "OrderId": {
        "title": "Order ID",
        "description": "The ID of the order.",
        "type": "string",
        "examples": ["O-01H5WQGHKCBB85MQFM68S9KJ5Q"]
      },
      "OrderDescription": {
        "title": "Description",
        "description": "Free format text reference for the order. The order description will not be visible to the end user. You will see this description in the Runa web portal.\n\nThis field is optional and can be omitted if not needed.\nIf not provided, the field will be set to `null` in the response.",
        "type": ["string", "null"],
        "maxLength": 128,
        "examples": ["Your own reference text"]
      },
      "OrderMetadata": {
        "title": "Metadata",
        "description": "A flexible field for you to attach additional, customer-specific data to the order. This is for your internal use, the information stored here will not be exposed to the end user.\n- All keys and their corresponding values must be strings\n- Each order supports up to 20 key-value pairs\n- Keys have a maximum length of 40 characters\n- Values can be up to 200 characters long.\n\nThis field is optional and can be omitted if not needed.\nIf not provided, the field will be set to `null` in the response.",
        "type": ["object", "null"],
        "maxProperties": 20,
        "propertyNames": {
          "type": "string",
          "maxLength": 40
        },
        "additionalProperties": {
          "type": "string",
          "maxLength": 200
        },
        "examples": [
          {
            "internal_id": "12345",
            "department": "marketing",
            "campaign": "summer_2024"
          }
        ]
      },
      "MonetaryAmount": {
        "title": "Monetary amount",
        "description": "A monetary amount in the major unit of its currency, given as a decimal string, for example `\"10.00\"`. Amounts are strings so that they survive a round trip without floating point precision loss. Send them as strings and parse them with a decimal type, not a float.",
        "type": "string",
        "format": "decimal",
        "pattern": "^[0-9]+(\\.[0-9]{1,2})?$",
        "examples": ["10.00"]
      },
      "Currency": {
        "type": "string",
        "format": "iso-4217",
        "pattern": "^[A-Z]{3}$",
        "description": "The currency of the account, represented by ISO 4217 currency codes. Check the [currencies](/reference/currencies) for a listing of supported currencies.",
        "examples": ["USD"]
      },
      "OrderStatus": {
        "title": "Order status",
        "description": "The status of the order.",
        "type": "string",
        "enum": ["COMPLETED", "FAILED", "PROCESSING"],
        "examples": ["PROCESSING"]
      },
      "DistributionEmailAddress": {
        "title": "Email Address",
        "description": "The email address of the end user to send the payout link to.",
        "examples": ["fred@example.com"],
        "type": "string",
        "format": "email"
      },
      "PayoutSelectionTemplateId": {
        "title": "Payout selection template ID",
        "description": "The template ID for a Payout Selection Template.",
        "examples": ["PT-01HPSF51G0ZWHJ3JTNWRH0WDYK"],
        "type": "string"
      },
      "RedemptionTemplateId": {
        "title": "User redemption template ID",
        "description": "The template ID for a User Redemption Template.",
        "examples": ["DT-01HPSF51G0ZWHJ3JTNWRH0WDYK"],
        "type": ["string", "null"]
      },
      "AccountPayment": {
        "title": "Account balance payment",
        "required": ["type"],
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "const": "ACCOUNT_BALANCE",
            "description": "Account balance payment."
          },
          "currency": { "$ref": "#/components/schemas/Currency" }
        },
        "description": "Account balance payment."
      },
      "CompletedOrderItem": {
        "title": "Completed order item",
        "type": "object",
        "properties": {
          "id": {
            "title": "ID",
            "description": "The ID of the order item.",
            "examples": ["E-NWPEKW4VL"],
            "type": "string"
          },
          "distribution_method": {
            "title": "Distribution Method",
            "description": "The distribution method used for the payout link.",
            "oneOf": [
              { "$ref": "#/components/schemas/EmailDistribution" },
              { "$ref": "#/components/schemas/LinkDistribution" },
              { "$ref": "#/components/schemas/RecipientDistribution" }
            ],
            "discriminator": {
              "propertyName": "type",
              "mapping": {
                "EMAIL": "#/components/schemas/EmailDistribution",
                "PAYOUT_LINK": "#/components/schemas/LinkDistribution",
                "RECIPIENT": "#/components/schemas/RecipientDistribution"
              }
            }
          },
          "products": {
            "title": "Products",
            "description": "The product(s) the end user can redeem the payout link on.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MultipleProduct"
              },
              {
                "$ref": "#/components/schemas/SingleProductWithUsageConfig"
              },
              {
                "$ref": "#/components/schemas/PayoutSelectionTemplateDetailed"
              },
              {
                "$ref": "#/components/schemas/UnknownProduct"
              }
            ],
            "discriminator": {
              "propertyName": "type",
              "mapping": {
                "SINGLE": "#/components/schemas/SingleProductWithUsageConfig",
                "MULTIPLE": "#/components/schemas/MultipleProduct",
                "TEMPLATE": "#/components/schemas/PayoutSelectionTemplateDetailed",
                "UNKNOWN": "#/components/schemas/UnknownProduct"
              }
            }
          },
          "face_value": {
            "title": "Face Value",
            "description": "The face value of the payout link.",
            "examples": ["10.00"],
            "$ref": "#/components/schemas/MonetaryAmount"
          },
          "price": {
            "title": "Price",
            "description": "The price paid for the payout link.",
            "examples": ["10.00"],
            "$ref": "#/components/schemas/MonetaryAmount"
          },
          "payout": {
            "title": "Payout",
            "description": "Payout link details",
            "$ref": "#/components/schemas/PayoutDetails"
          },
          "currency": {
            "description": "The currency of the payout link, represented by ISO 4217 currency codes.",
            "$ref": "#/components/schemas/Currency"
          }
        },
        "required": [
          "id",
          "distribution_method",
          "products",
          "face_value",
          "price",
          "payout"
        ]
      },
      "OrderSummary": {
        "title": "Order summary",
        "description": "Used for orders that have completed. This class is typically used when returning a *list* of orders to the client.",
        "required": [
          "id",
          "status",
          "created_at",
          "payment_method",
          "currency",
          "total_price",
          "total_discount"
        ],
        "type": "object",
        "properties": {
          "id": { "$ref": "#/components/schemas/OrderId" },
          "status": { "$ref": "#/components/schemas/OrderStatus" },
          "created_at": {
            "title": "Created At",
            "description": "UTC timestamp, in ISO 8601 format, when the order was submitted.",
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "title": "Completed At",
            "description": "UTC timestamp, in ISO 8601 format, when the order was completed.",
            "type": "string",
            "format": "date-time"
          },
          "description": { "$ref": "#/components/schemas/OrderDescription" },
          "payment_method": {
            "title": "Payment Method",
            "description": "The payment method used for the order.",
            "$ref": "#/components/schemas/AccountPayment"
          },
          "currency": {
            "description": "The currency of the order, represented by ISO 4217 currency codes. Please check the currency section in the guidelines for how to use this field.",
            "$ref": "#/components/schemas/Currency"
          },
          "total_price": {
            "title": "Total Price",
            "description": "The total price of the order. This _includes_ any applicable fees.",
            "examples": ["10.00"],
            "$ref": "#/components/schemas/MonetaryAmount"
          },
          "total_discount": {
            "title": "Total Discount",
            "description": "The total discount of the order.",
            "examples": ["1.00"],
            "$ref": "#/components/schemas/MonetaryAmount"
          }
        }
      },
      "AsyncAcceptedOrder": {
        "title": "Accepted order",
        "required": ["id", "status"],
        "type": "object",
        "properties": {
          "id": { "$ref": "#/components/schemas/OrderId" },
          "status": {
            "type": "string",
            "const": "PROCESSING",
            "description": "Always `PROCESSING` for this schema."
          }
        }
      },
      "CompletedOrder": {
        "title": "Completed order",
        "allOf": [
          {
            "$ref": "#/components/schemas/Order"
          },
          {
            "properties": {
              "status": {
                "type": "string",
                "enum": ["COMPLETED"],
                "description": "Always `COMPLETED` for this schema."
              }
            }
          }
        ]
      },
      "OrderCreationResult": {
        "title": "Order creation result",
        "description": "The body of `POST /order`. `COMPLETED` (HTTP 200) when the order was executed synchronously, `PROCESSING` (HTTP 202) when it was accepted for asynchronous processing. Asynchronous is the default execution mode; send `X-Execution-Mode: sync` for the synchronous path. Branch on `status`.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/CompletedOrder"
          },
          {
            "$ref": "#/components/schemas/AsyncAcceptedOrder"
          }
        ],
        "discriminator": {
          "propertyName": "status",
          "mapping": {
            "COMPLETED": "#/components/schemas/CompletedOrder",
            "PROCESSING": "#/components/schemas/AsyncAcceptedOrder"
          }
        }
      },
      "CompletedOrderWebhook": {
        "title": "Completed order webhook",
        "type": "object",
        "description": "Webhook message sent when an order has completed processing.",
        "allOf": [
          {
            "$ref": "#/components/schemas/OrderSummary"
          },
          {
            "properties": {
              "status": {
                "type": "string",
                "enum": ["COMPLETED"],
                "description": "Always `COMPLETED` for this schema."
              }
            }
          }
        ]
      },
      "FailedOrderWebhook": {
        "title": "Failed order",
        "type": "object",
        "description": "Webhook message sent when an order has failed to process.",
        "required": ["id", "status"],
        "properties": {
          "id": { "$ref": "#/components/schemas/OrderId" },
          "status": {
            "type": "string",
            "const": "FAILED"
          }
        }
      },
      "Order": {
        "title": "Order",
        "description": "Used for an order that has completed. This class is typically used when returning a *single order* to the client.",
        "type": "object",
        "allOf": [
          {
            "$ref": "#/components/schemas/OrderSummary"
          },
          {
            "required": ["items"],
            "properties": {
              "items": {
                "title": "Items",
                "description": "The list of items that were included in the order. Each _item_ represents a single payout link.",
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/CompletedOrderItem"
                }
              },
              "transaction_detail": {
                "$ref": "#/components/schemas/TransactionDetail"
              },
              "metadata": { "$ref": "#/components/schemas/OrderMetadata" }
            }
          }
        ]
      },
      "ProcessingOrder": {
        "title": "Processing order",
        "required": ["id", "status", "message"],
        "type": "object",
        "properties": {
          "id": { "$ref": "#/components/schemas/OrderId" },
          "status": {
            "type": "string",
            "const": "PROCESSING",
            "description": "Always `PROCESSING` for this schema."
          },
          "message": {
            "title": "Message",
            "description": "Human readable message describing the status of the order.",
            "type": "string"
          }
        },
        "description": "Order that has been accepted but is not complete."
      },
      "EmailDistribution": {
        "title": "Email",
        "required": ["type", "email_address"],
        "type": "object",
        "properties": {
          "type": { "type": "string", "const": "EMAIL" },
          "email_address": {
            "$ref": "#/components/schemas/DistributionEmailAddress"
          },
          "template_id": { "$ref": "#/components/schemas/RedemptionTemplateId" }
        },
        "description": "Email distribution. Send the payout link to the end user directly via email."
      },
      "LinkDistribution": {
        "title": "Link",
        "required": ["type"],
        "type": "object",
        "properties": {
          "type": { "type": "string", "const": "PAYOUT_LINK" },
          "template_id": { "$ref": "#/components/schemas/RedemptionTemplateId" }
        },
        "description": "Link distribution. Send the payout link to the end user yourself."
      },
      "RecipientDistribution": {
        "title": "Recipient",
        "description": "Recipient distribution. Currently this method is only supported for distributing payment type products. For subsequent orders to known recipients we will attempt to make a repeat payout.",
        "required": ["type", "recipient_reference", "email_address"],
        "type": "object",
        "properties": {
          "type": { "type": "string", "const": "RECIPIENT" },
          "recipient_reference": {
            "title": "Recipient Reference",
            "description": "A customer provided reference to identify an individual recipient. It must be unique per recipient. When the same reference is used for a second order this will trigger a repeat payout. This is a free-form string limited to 255 characters. It can only contain alphanumeric characters, dashes, underscores, dots, and at-signs.",
            "examples": ["abc123"],
            "type": "string",
            "maxLength": 255,
            "pattern": "^[A-Za-z0-9-_@.]+$"
          },
          "email_address": {
            "$ref": "#/components/schemas/DistributionEmailAddress"
          },
          "template_id": { "$ref": "#/components/schemas/RedemptionTemplateId" }
        }
      },
      "PayoutSelectionTemplate": {
        "title": "Template ID",
        "required": ["type", "template_id"],
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "const": "TEMPLATE"
          },
          "template_id": {
            "$ref": "#/components/schemas/PayoutSelectionTemplateId"
          }
        },
        "description": "Payout selection template. Template having predefined set of products."
      },
      "PayoutSelectionTemplateDetailed": {
        "title": "Template",
        "required": ["type", "template_id"],
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "const": "TEMPLATE"
          },
          "template_id": {
            "$ref": "#/components/schemas/PayoutSelectionTemplateId"
          },
          "values": {
            "title": "Values",
            "description": "The codes for products selected for Payout Selection Template.",
            "examples": [["AMZ-US", "AIRBNB-US"]],
            "minItems": 2,
            "type": "array",
            "items": {
              "type": "string"
            },
            "uniqueItems": true
          }
        },
        "description": "Payout selection template. Template having predefined set of products."
      },
      "AccountPaymentRequest": {
        "title": "Account balance payment request",
        "required": ["type", "currency"],
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "const": "ACCOUNT_BALANCE",
            "description": "Account balance payment method."
          },
          "currency": { "$ref": "#/components/schemas/Currency" }
        },
        "description": "Pay using your account balance."
      },
      "CreateOrderRequest": {
        "title": "New order",
        "required": ["payment_method", "items"],
        "type": "object",
        "properties": {
          "payment_method": {
            "title": "Payment Method",
            "description": "Payment method for the order. Select the `ACCOUNT_BALANCE` you want to pay for the order from",
            "$ref": "#/components/schemas/AccountPaymentRequest"
          },
          "items": {
            "title": "Items",
            "description": "The list of items to be included in the order. Each item ordered results in a single payout link. The maximum number of items per order is 200.",
            "minItems": 1,
            "maxItems": 200,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CreateOrderItem"
            }
          },
          "description": { "$ref": "#/components/schemas/OrderDescription" },
          "metadata": { "$ref": "#/components/schemas/OrderMetadata" }
        }
      },
      "CreateOrderItem": {
        "title": "Create order item",
        "required": ["face_value", "distribution_method", "products"],
        "type": "object",
        "properties": {
          "face_value": {
            "title": "Face Value",
            "description": "Face value of the payout link. The currency of the face value is inferred from the product selection.\n\nWhat value is allowed depends on the product mode:\n- When ordering a `SINGLE` product this field follows the allowed values from the selected product.\n- If using `MULTIPLE` or `TEMPLATE` this value must be: equal or greater than the minimum face value of the products selected and be a whole number.",
            "examples": ["10.00"],
            "$ref": "#/components/schemas/MonetaryAmount"
          },
          "distribution_method": {
            "title": "Distribution Method",
            "description": "How the payout link reaches the end user. Choose `EMAIL` for Runa to email the link directly, `PAYOUT_LINK` to receive the link in the response and distribute it yourself, or `RECIPIENT` to send it to a known recipient identified by your own reference, which also enables repeat payouts.",
            "oneOf": [
              { "$ref": "#/components/schemas/EmailDistribution" },
              { "$ref": "#/components/schemas/LinkDistribution" },
              { "$ref": "#/components/schemas/RecipientDistribution" }
            ],
            "discriminator": {
              "propertyName": "type",
              "mapping": {
                "EMAIL": "#/components/schemas/EmailDistribution",
                "PAYOUT_LINK": "#/components/schemas/LinkDistribution",
                "RECIPIENT": "#/components/schemas/RecipientDistribution"
              }
            }
          },
          "products": {
            "title": "Products",
            "description": "What the end user can redeem the face value on. Choose `SINGLE` for one specific product, `MULTIPLE` for a choice of several products, or `TEMPLATE` to use a saved payout selection template.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/SingleProductWithUsageConfig"
              },
              {
                "$ref": "#/components/schemas/MultipleProduct"
              },
              {
                "$ref": "#/components/schemas/PayoutSelectionTemplate"
              }
            ],
            "discriminator": {
              "propertyName": "type",
              "mapping": {
                "SINGLE": "#/components/schemas/SingleProductWithUsageConfig",
                "MULTIPLE": "#/components/schemas/MultipleProduct",
                "TEMPLATE": "#/components/schemas/PayoutSelectionTemplate"
              }
            }
          }
        }
      },
      "OrderEstimateItem": {
        "title": "Order item estimate",
        "required": [
          "products",
          "face_value",
          "price",
          "discount_multiplier",
          "currency"
        ],
        "type": "object",
        "properties": {
          "products": {
            "title": "Products",
            "description": "Choose `SINGLE` if you want the end user to redeem the face value on a single specific product. Choose `MULTIPLE` if the end user can choose to spend the face value across multiple products.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MultipleProduct"
              },
              {
                "$ref": "#/components/schemas/SingleProduct"
              }
            ],
            "discriminator": {
              "propertyName": "type",
              "mapping": {
                "SINGLE": "#/components/schemas/SingleProduct",
                "MULTIPLE": "#/components/schemas/MultipleProduct"
              }
            }
          },
          "face_value": {
            "title": "Face Value",
            "description": "Face value of the payout link.",
            "examples": ["10.00"],
            "$ref": "#/components/schemas/MonetaryAmount"
          },
          "price": {
            "title": "Price",
            "description": "The price of the order item. This is before `discount_multiplier` is applied.",
            "examples": ["10.00"],
            "$ref": "#/components/schemas/MonetaryAmount"
          },
          "discount_multiplier": {
            "$ref": "#/components/schemas/ProductDiscountMultiplier"
          },
          "currency": {
            "description": "The currency of the product, represented by ISO 4217 currency codes. Please check the currency section in the guidelines for how to use this field.",
            "$ref": "#/components/schemas/Currency"
          }
        },
        "description": "The computed discount for an order item."
      },
      "OrderEstimateRequestItem": {
        "title": "Estimate item",
        "required": ["products", "face_value"],
        "type": "object",
        "properties": {
          "products": {
            "title": "Products",
            "description": "Choose `SINGLE` if you want the end user to redeem the face value on a single specific product. Choose `MULTIPLE` if the end user can choose to spend the face value across multiple products.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/MultipleProduct"
              },
              {
                "$ref": "#/components/schemas/SingleProduct"
              }
            ],
            "discriminator": {
              "propertyName": "type",
              "mapping": {
                "SINGLE": "#/components/schemas/SingleProduct",
                "MULTIPLE": "#/components/schemas/MultipleProduct"
              }
            }
          },
          "face_value": {
            "title": "Face Value",
            "description": "Face value of the payout link.",
            "examples": ["10.00"],
            "$ref": "#/components/schemas/MonetaryAmount"
          }
        },
        "description": "A proposed order item within an order price request."
      },
      "OrderEstimateRequest": {
        "title": "Order estimate request",
        "required": ["payment_method", "items"],
        "type": "object",
        "properties": {
          "payment_method": {
            "title": "Payment Method",
            "description": "Payment method for the order. Select the `ACCOUNT_BALANCE` you want to pay for the order from.",
            "$ref": "#/components/schemas/AccountPaymentRequest"
          },
          "items": {
            "title": "Items",
            "description": "List of order items for price estimation.",
            "minItems": 1,
            "maxItems": 500,
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderEstimateRequestItem"
            }
          }
        },
        "description": "Request for a price estimate for an order."
      },
      "OrderEstimateResponse": {
        "title": "Order estimate response",
        "required": [
          "payment_method",
          "items",
          "currency",
          "total_discount",
          "total_price"
        ],
        "type": "object",
        "properties": {
          "payment_method": {
            "title": "Payment Method",
            "$ref": "#/components/schemas/AccountPayment"
          },
          "items": {
            "title": "Items",
            "description": "List of order items with price and discount.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderEstimateItem"
            }
          },
          "currency": {
            "description": "The currency of the order, represented by ISO 4217 currency codes. Please check the currency section in the guidelines for how to use this field.",
            "$ref": "#/components/schemas/Currency"
          },
          "total_discount": {
            "title": "Total Discount",
            "description": "Total discount on the entire order.",
            "examples": ["0.50"],
            "$ref": "#/components/schemas/MonetaryAmount"
          },
          "total_price": {
            "title": "Total Price",
            "description": "Total price of the entire order.",
            "examples": ["9.50"],
            "$ref": "#/components/schemas/MonetaryAmount"
          },
          "transaction_detail": {
            "$ref": "#/components/schemas/TransactionDetail"
          }
        },
        "description": "Response object for a order price estimate."
      },
      "TransactionDetail": {
        "title": "Transaction detail",
        "description": "A mapping of the subtotal of the order using the payout currency as a key.",
        "type": "object",
        "examples": [
          {
            "USD": {
              "value": "10.00",
              "fx": null
            }
          }
        ],
        "propertyNames": {
          "$ref": "#/components/schemas/Currency"
        },
        "additionalProperties": {
          "$ref": "#/components/schemas/TransactionDetailEntry"
        }
      },
      "TransactionDetailEntry": {
        "type": "object",
        "title": "Transaction detail entry",
        "description": "A subtotal of the value purchased and associated fees and data about the transaction.",
        "properties": {
          "value": {
            "title": "Value",
            "description": "The total value purchased of a payout link currency.",
            "examples": ["10.00"],
            "$ref": "#/components/schemas/MonetaryAmount"
          },
          "fx": {
            "title": "FX",
            "description": "Present only when the payment method currency differs from the transaction detail currency. `null` otherwise.",
            "oneOf": [
              { "$ref": "#/components/schemas/TransactionDetailFx" },
              { "type": "null" }
            ]
          }
        },
        "required": ["value"]
      },
      "TransactionDetailFx": {
        "type": "object",
        "title": "FX details",
        "description": "Provides details on fx conversion for an order transaction detail. Present when the payment method currency is different from the transaction detail currency.",
        "properties": {
          "rate": {
            "title": "FX Rate",
            "description": "The FX rate received for the transaction between the payout currency and payment currency.",
            "type": "string",
            "examples": ["1.234"]
          },
          "rate_symbol": {
            "title": "FX Rate symbol",
            "description": "The currency pair associated with the FX transaction.",
            "type": "string",
            "examples": ["GBPUSD"]
          },
          "fee": {
            "title": "Fee",
            "description": "The fee charged for making this transaction.",
            "type": "object",
            "properties": {
              "value": {
                "title": "Value",
                "description": "The value of the fee.",
                "examples": ["0.02"],
                "$ref": "#/components/schemas/MonetaryAmount"
              },
              "currency": {
                "title": "Currency",
                "description": "The currency of the fee.",
                "type": "string",
                "examples": ["USD"]
              }
            },
            "required": ["value", "currency"]
          }
        },
        "required": ["rate", "rate_symbol", "fee"]
      },
      "Page": {
        "title": "Page",
        "type": "object",
        "properties": {
          "limit": {
            "title": "Limit",
            "description": "How many records the current page is limited to.",
            "examples": [100],
            "type": "integer"
          }
        }
      },
      "PageCursors": {
        "title": "Cursors",
        "type": "object",
        "properties": {
          "after": {
            "title": "After",
            "description": "Cursor to query the next page.",
            "examples": ["A-789"],
            "type": "string"
          },
          "before": {
            "title": "Before",
            "description": "Cursor to query the previous page.",
            "examples": ["A-123"],
            "type": "string"
          }
        }
      },
      "Pagination": {
        "title": "Pagination",
        "required": ["cursors", "page"],
        "type": "object",
        "description": "Information about the page of results returned. See [pagination](/reference/pagination) for more information on how to page through results.",
        "properties": {
          "cursors": {
            "title": "Cursors",
            "description": "Pagination cursors, use the `after` cursor to page forward and the `before` cursor to page backward.",
            "$ref": "#/components/schemas/PageCursors"
          },
          "page": {
            "title": "Page",
            "description": "Extra information about the current page.",
            "$ref": "#/components/schemas/Page"
          }
        }
      },
      "SingleProduct": {
        "title": "Single product",
        "required": ["type", "value"],
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "const": "SINGLE"
          },
          "value": {
            "title": "Value",
            "description": "The code for the product the end user will get when redeeming their payout link.",
            "minLength": 1,
            "examples": ["AMZ-US"],
            "type": "string"
          }
        },
        "description": "Single product. The end user will be able to redeem the payout link for this specific product."
      },
      "SingleProductWithUsageConfig": {
        "title": "Single",
        "required": ["type", "value"],
        "type": "object",
        "examples": [
          {
            "type": "SINGLE",
            "value": "AMZ-US"
          }
        ],
        "properties": {
          "type": {
            "type": "string",
            "const": "SINGLE"
          },
          "value": {
            "title": "Value",
            "description": "The code for the product the end user will get when redeeming their payout link.",
            "minLength": 1,
            "examples": ["AMZ-US"],
            "type": "string"
          },
          "usage_config": {
            "description": "Optional. **Only applicable to prepaid Visa cards.** Attaches an MCC-rules template to the issued card. Ignored for all other products. See [Card spend controls](/features/prepaid-visa/spend-controls) for a worked example. When set on a prepaid Visa card order, it is returned in the order details.",
            "$ref": "#/components/schemas/UsageConfig"
          }
        },
        "description": "Single product. The end user will be able to redeem the payout link for this specific product."
      },
      "UsageConfig": {
        "title": "Usage configuration",
        "type": "object",
        "description": "Additional configuration applied to the issued product. Only applicable to prepaid Visa cards.",
        "properties": {
          "spend_rules_template_id": {
            "title": "MCC rules template ID",
            "description": "Identifier of a Runa-authored MCC-rules template applied to the issued card.\n\nOnly applicable to prepaid Visa cards. A single template is applied per card, with multiple rules that either allows or blocks transactions for a given merchant category bundled inside that one template.",
            "type": "string",
            "pattern": "^PSR-[0-9A-HJKMNP-TV-Z]{26}$",
            "examples": ["PSR-XXXXXXXXXXXXXXXXXXXXXXXXXX"]
          }
        }
      },
      "MultipleProduct": {
        "title": "Multiple",
        "required": ["type", "values"],
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "const": "MULTIPLE"
          },
          "values": {
            "title": "Values",
            "description": "The codes for the products the end user can choose from when redeeming their payout link. All products _must_ use the same currency.",
            "examples": [["AMZ-US", "AIRBNB-US"]],
            "minItems": 2,
            "type": "array",
            "items": {
              "type": "string"
            },
            "uniqueItems": true
          }
        },
        "description": "Multiple products. The end user will be able to split the payout link's value between these products."
      },
      "UnknownProduct": {
        "title": "Unknown",
        "type": "object",
        "description": "Product(s) unknown. It was not possible to determine which products were included in the order.",
        "required": ["type"],
        "properties": {
          "type": {
            "title": "Type",
            "description": "It is not currently possible to determine which products were selected when this item was ordered.",
            "type": "string",
            "const": "UNKNOWN"
          }
        }
      },
      "ProductUpdateWebhook": {
        "title": "Product update webhook",
        "type": "object",
        "required": ["product_code", "old_state", "new_state", "timestamp"],
        "properties": {
          "product_code": {
            "type": "string",
            "description": "The code of the product that was updated.",
            "examples": ["XYZ-US"]
          },
          "old_state": {
            "description": "The state of the product before the update.",
            "$ref": "#/components/schemas/ProductUpdateState"
          },
          "new_state": {
            "description": "The state of the product after the update.",
            "$ref": "#/components/schemas/ProductUpdateState"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "UTC timestamp, in ISO 8601 format, when the product was updated."
          }
        }
      },
      "ProductUpdateState": {
        "title": "Product update state",
        "description": "The state of the product either before or after the update.",
        "type": "object",
        "required": ["price_multiplier", "is_orderable"],
        "properties": {
          "price_multiplier": {
            "$ref": "#/components/schemas/ProductDiscountMultiplier"
          },
          "is_orderable": { "$ref": "#/components/schemas/ProductIsOrderable" },
          "denominations": {
            "$ref": "#/components/schemas/ProductDenominations"
          }
        }
      },
      "PayoutStatus": {
        "title": "Payout status",
        "type": "string",
        "description": "Current status of the payout link. An `ACTIVE` link is live but has not been claimed yet, it will change to `CLAIMED` once that has happened. If you request a cancellation the status will reflect this as `CANCELLED`. Finally, if your account is configured with link expiry, when the link itself expires it will be marked as `EXPIRED` — this is independent of the underlying product's own expiry policy.",
        "enum": ["ACTIVE", "CLAIMED", "CANCELLED", "EXPIRED"]
      },
      "PayoutDetails": {
        "title": "Payout details",
        "type": "object",
        "properties": {
          "status": {
            "$ref": "#/components/schemas/PayoutStatus"
          },
          "status_updated_at": {
            "title": "Status Updated At",
            "description": "Time that the payout link status was last updated",
            "type": "string",
            "format": "date-time"
          },
          "url": {
            "title": "Url",
            "description": "The URL (payout link) the end user uses to redeem.",
            "type": "string"
          },
          "expiry_date": {
            "title": "Expiry Date",
            "description": "When the payout link expires. This is the expiry of the payout link itself, not the underlying gift card or product.\n\nIf your account does not have expiry of links enabled this field will be set to `null`, the link does not expire.",
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": ["status", "status_updated_at", "url"]
      },
      "ValidationErrorItem": {
        "title": "Validation error item",
        "required": ["type", "message", "location"],
        "type": "object",
        "properties": {
          "type": {
            "title": "Type",
            "description": "The type of error encountered.",
            "type": "string",
            "examples": ["value_error.number.not_ge"]
          },
          "message": {
            "title": "Message",
            "description": "A human readable summary of the error.",
            "type": "string",
            "examples": ["ensure this value is greater than or equal to 1"]
          },
          "location": {
            "title": "Location",
            "description": "The location of the error in the submitted entity.",
            "type": "array",
            "items": {
              "type": "string"
            },
            "examples": [["items", "0", "face_value"]]
          }
        },
        "description": "A single validation error. The type indicates the error type and the message provides a human readable summary of the error. The location provides a path to the key in the request body."
      },
      "ValidationErrorResponse": {
        "title": "Validation error",
        "required": ["type", "message", "details"],
        "type": "object",
        "properties": {
          "type": {
            "title": "Type",
            "description": "An error code or type.",
            "type": "string",
            "examples": ["validation_error"]
          },
          "message": {
            "title": "Message",
            "description": "A human readable summary of the error.",
            "type": "string",
            "examples": [
              "There were one or more problems processing your request, see details key."
            ]
          },
          "help": {
            "title": "Help",
            "description": "Additional information that pertains to the error. `null` when there is nothing further to add.",
            "type": ["string", "null"],
            "examples": [null]
          },
          "details": {
            "title": "Details",
            "description": "Additional details regarding the error.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ValidationErrorItem"
            }
          }
        },
        "description": "A validation error response. Returned when the request failed validation. This response can contain multiple validation errors, see the details key for each."
      },
      "Product": {
        "type": "object",
        "description": "Product details",
        "properties": {
          "name": {
            "type": "string",
            "description": "The name of the product.",
            "examples": ["Example Merchant"]
          },
          "code": {
            "type": "string",
            "description": "A unique code identifying the product. Use this code when placing an order. \n\n_For `subscription` products, this code identifies the top level product. You must use the `subscription_plan_code` instead when ordering._",
            "examples": ["XYZ-US"]
          },
          "currency": {
            "description": "The currency of the product, represented by an ISO 4217 currency code. See [currencies](/reference/currencies) for a list of supported currencies.",
            "$ref": "#/components/schemas/Currency"
          },
          "state": {
            "type": "string",
            "enum": ["LIVE", "TEMPORARILY_DISABLED", "TEMPORARILY_DEGRADED"],
            "description": "The current state of the product.",
            "examples": ["LIVE"]
          },
          "is_orderable": { "$ref": "#/components/schemas/ProductIsOrderable" },
          "payout_type": {
            "type": "string",
            "enum": ["gift_card", "subscription", "payment"],
            "description": "The type of payout - this field will tell you the key of the additional object details that correspond to each payout type. The types currently supported are `gift_card`, `subscription`, or `payment`. Your implementation should account for additional payout types being added in the future."
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "List of the categories that the product belongs to. You can fetch the list of categories using the [`GET /product/categories` endpoint](/reference/2024-02-05/endpoint/products/categories).",
            "examples": [["food-and-drink", "entertainment"]]
          },
          "countries_redeemable_in": {
            "type": "array",
            "items": {
              "type": "string",
              "pattern": "^[A-Z]{2}$",
              "description": "ISO 3166 ALPHA-2 country code"
            },
            "description": "Countries where the payout can be spent.",
            "examples": [["US"]]
          },
          "customer_service": {
            "$ref": "#/components/schemas/ProductCustomerService"
          },
          "discount_multiplier": {
            "$ref": "#/components/schemas/ProductDiscountMultiplier"
          },
          "availability": {
            "type": "string",
            "enum": ["stocked", "realtime"],
            "description": "The availability type of the product.",
            "examples": ["realtime"]
          },
          "gift_card": {
            "description": "Specific details about the gift card product, only populated when the `payout_type` is `gift_card`.",
            "allOf": [
              {
                "$ref": "#/components/schemas/GiftCardOrSubscriptionDetails"
              },
              {
                "type": "object",
                "properties": {
                  "denominations": {
                    "$ref": "#/components/schemas/ProductDenominations"
                  }
                }
              }
            ]
          },
          "subscription": {
            "description": "Details about the subscription product, only populated when the `payout_type` is `subscription`.",
            "allOf": [
              {
                "$ref": "#/components/schemas/GiftCardOrSubscriptionDetails"
              },
              {
                "type": "object",
                "properties": {
                  "subscription_plans": {
                    "description": "A list of subscription plans available for the product. You must use the `subscription_plan_code` when ordering a subscription plan, not the top-level `code`.",
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ProductSubscriptionPlan"
                    }
                  }
                }
              }
            ]
          },
          "payment": {
            "description": "Details about the payment product, only populated when the `payout_type` is `payment`.",
            "$ref": "#/components/schemas/ProductPayment"
          }
        },
        "required": [
          "categories",
          "code",
          "countries_redeemable_in",
          "currency",
          "customer_service",
          "discount_multiplier",
          "name",
          "state",
          "is_orderable",
          "payout_type"
        ]
      },
      "GiftCardOrSubscriptionDetails": {
        "type": "object",
        "properties": {
          "assets": {
            "$ref": "#/components/schemas/ProductAssets"
          },
          "balance_check_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "URL to check the gift card balance. This will be a provider specific URL that a consumer can use to check the balance of the gift card.",
            "examples": ["https://merchant.example.com/balance-check"]
          },
          "content_resources": {
            "$ref": "#/components/schemas/ContentResources"
          },
          "expiry": {
            "$ref": "#/components/schemas/ProductExpiry"
          },
          "redeemable_at": {
            "description": "Defines where the gift card can be redeemed. Options are `all` for both online and in-store, `in-store` for in-store only, and `online` for online only.",
            "type": "string",
            "enum": ["all", "online", "in-store"],
            "examples": ["all"]
          },
          "website_url": {
            "description": "The URL of the website for the product. This is the URL that a consumer can use to either redeem the payout or view details about where they can redeem the payout.",
            "type": ["string", "null"],
            "format": "uri",
            "examples": ["https://merchant.example.com"]
          },
          "barcode_format": {
            "type": ["string", "null"],
            "enum": [
              "code-128",
              "code-39",
              "QR",
              "ean-13",
              "pdf417",
              "ITF",
              "DATA_MATRIX",
              "other",
              null
            ],
            "description": "The barcode format of the product.",
            "examples": ["code-128"]
          },
          "e_code_usage_type": {
            "type": "string",
            "enum": ["undefined", "url-recommended", "url-only", "code"],
            "description": "The e-code usage type of the product.",
            "examples": ["url-only"]
          }
        }
      },
      "ProductSubscriptionPlan": {
        "type": "object",
        "properties": {
          "length_unit": {
            "description": "The unit of time for the subscription plan. Currently `DAYS` and `MONTHS` are supported.",
            "type": "string",
            "enum": ["DAYS", "MONTHS"],
            "examples": ["MONTHS"]
          },
          "length": {
            "type": "integer",
            "description": "The length of the subscription plan using the `length_unit`.",
            "examples": [12]
          },
          "name": {
            "type": "string",
            "description": "The name of the subscription plan.",
            "examples": ["3 month subscription"]
          },
          "price": {
            "description": "The price of the subscription plan.",
            "examples": ["10.00"],
            "$ref": "#/components/schemas/MonetaryAmount"
          },
          "subscription_plan_code": {
            "description": "Use this code during order creation, rather than the top level `code`.",
            "type": "string",
            "examples": ["XYZ-US-SUB-1"]
          }
        }
      },
      "ProductPayment": {
        "type": "object",
        "properties": {
          "assets": {
            "type": "object",
            "required": ["icon_image_url", "primary_color"],
            "properties": {
              "icon_image_url": {
                "$ref": "#/components/schemas/ProductIconImageUrl"
              },
              "primary_color": {
                "$ref": "#/components/schemas/ProductPrimaryColor"
              }
            }
          },
          "denominations": {
            "type": "object",
            "required": ["minimum_value", "maximum_value"],
            "properties": {
              "minimum_value": {
                "$ref": "#/components/schemas/MonetaryAmount",
                "description": "The minimum denomination value available for the product.",
                "examples": ["10.00"]
              },
              "maximum_value": {
                "$ref": "#/components/schemas/MonetaryAmount",
                "description": "The maximum denomination value available for the product.",
                "examples": ["100.00"]
              }
            }
          },
          "content_resources": {
            "$ref": "#/components/schemas/ContentResources"
          }
        },
        "required": ["assets", "denominations"]
      },
      "ProductCustomerService": {
        "type": "object",
        "description": "Contact information for customer service related to the product. Suitable for displaying to the customer.",
        "properties": {
          "phone_number": {
            "type": ["string", "null"],
            "description": "The customer service phone number.",
            "examples": ["+1234567890"]
          },
          "website_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "The customer service website URL.",
            "examples": ["https://merchant.example.com/customer-service"]
          }
        }
      },
      "ProductDenominations": {
        "type": "object",
        "description": "Defines the denomination options available for the product, including ranges and types.",
        "properties": {
          "type": {
            "type": "string",
            "enum": ["open", "fixed"],
            "description": "The type of denomination. Can be `open` or `fixed`. `open` is any amount between the minimum and maximum value. `fixed` is limited to those returned in the `available_list`.",
            "examples": ["fixed"]
          },
          "minimum_value": {
            "$ref": "#/components/schemas/MonetaryAmount",
            "description": "The minimum denomination value available for the product.",
            "examples": ["10.00"]
          },
          "maximum_value": {
            "$ref": "#/components/schemas/MonetaryAmount",
            "description": "The maximum denomination value available for the product.",
            "examples": ["100.00"]
          },
          "available_list": {
            "type": ["array", "null"],
            "items": { "$ref": "#/components/schemas/MonetaryAmount" },
            "description": "A list of available denominations for the product. Will be `null` if the `type` is `open`.",
            "examples": [["10.00", "20.00", "50.00", "100.00"]]
          }
        }
      },
      "ProductExpiry": {
        "type": "object",
        "properties": {
          "date_policy": {
            "type": ["string", "null"],
            "description": "Text description of the policy, suitable for displaying to the customer.",
            "examples": ["Expires 2 years from issue date"]
          },
          "in_months": {
            "type": "integer",
            "description": "Specifies the number of months until the gift expires.",
            "examples": [12]
          },
          "type": {
            "type": "string",
            "description": "The type of expiry policy. \n\n | Type | Description | \n | --- | --- | \n | `from-last-use` | The expiration period starts after the gift is used for a purchase. | \n | `from-last-balance-check` | The expiration period starts after the gift balance is checked using phone or online tools. | \n | `from-issue-date` | The expiration period starts from the date the gift was purchased. | \n | `indefinite` | The gift card does not expire and remains valid indefinitely. | \n | `do-not-show` | No expiration information is displayed. |",
            "enum": [
              "from-last-use",
              "from-last-balance-check",
              "from-issue-date",
              "indefinite",
              "do-not-show"
            ],
            "examples": ["from-issue-date"]
          }
        }
      },
      "ProductIsOrderable": {
        "type": "boolean",
        "description": "Indicates whether or not you are able to order the product. You should use this detail to determine whether or not to display the product to your end users.\n\nWe recommend that you only display products to customers when this field is `true` - we will reject any orders placed for products where this is `false`. You can filter by `is_orderable` to only return products that can be ordered in the list endpoint."
      },
      "ProductDiscountMultiplier": {
        "type": "string",
        "pattern": "^[0-9]+\\.[0-9]{1,4}$",
        "description": "The discount multiplier used when ordering. `0` means no discount and `0.1` means 10% discount. The discount is applied on the price of the order item before any fees are applied.",
        "examples": ["0.05"]
      },
      "ProductIconImageUrl": {
        "type": "string",
        "format": "uri",
        "description": "The URL of the icon image for the product. Includes a `v` query parameter that changes whenever the underlying image content changes - treat the full URL, including the query string, as the cache key and re-fetch when it changes.",
        "examples": [
          "https://gift.runa.io/static/product_assets/XYZ-US/XYZ-US-icon.png?v=1690000000"
        ]
      },
      "ProductPrimaryColor": {
        "type": "string",
        "pattern": "^#[0-9A-Fa-f]{6}$",
        "description": "The primary color of the product.",
        "examples": ["#000000"]
      },
      "ProductAssets": {
        "title": "Product assets",
        "description": "Graphical assets for the product, including card image, icon image, and primary color.",
        "type": "object",
        "properties": {
          "card_image_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "The URL of the card image for the product. Includes a `v` query parameter that changes whenever the underlying image content changes - treat the full URL, including the query string, as the cache key and re-fetch when it changes.",
            "examples": [
              "https://gift.runa.io/static/product_assets/XYZ-US/XYZ-US-card.png?v=1690000000"
            ]
          },
          "icon_image_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "The URL of the icon image for the product. Includes a `v` query parameter that changes whenever the underlying image content changes - treat the full URL, including the query string, as the cache key and re-fetch when it changes.",
            "examples": [
              "https://gift.runa.io/static/product_assets/XYZ-US/XYZ-US-icon.png?v=1690000000"
            ]
          },
          "primary_color": {
            "type": ["string", "null"],
            "pattern": "^#[0-9A-Fa-f]{6}$",
            "examples": ["#000000"]
          }
        }
      },
      "ContentResourcesLocale": {
        "type": "string",
        "description": "What locale the content resources are in. This is an [IETF language tag](https://en.wikipedia.org/wiki/IETF_language_tag) using an underscore to separate the language and country codes.",
        "pattern": "^[a-z]{2}_[A-Z]{2}$",
        "examples": ["en_US"]
      },
      "ContentResources": {
        "title": "Content resources",
        "description": "Content resources provide additional information about the product, including:\n\n- Product description\n- Disclaimers\n- Refund policy\n- Reissuance policy \n- Terms and conditions\n- Redemption instructions\n\nThis content can be returned in different formats based on the `content` query parameter in the [get product endpoint](/reference/2024-02-05/endpoint/products/get#parameter-content). The list endpoint only supports returning content as URLs.\n\nContent fields will be present when content is available, and `null` when content has been removed. We update content periodically - if content has been removed, requests will return a `403` or `404` error. Your implementation should handle these errors gracefully.",
        "oneOf": [
          { "$ref": "#/components/schemas/ContentResourcesUrl" },
          { "$ref": "#/components/schemas/ContentResourcesMarkdown" },
          { "$ref": "#/components/schemas/ContentResourcesHtml" }
        ]
      },
      "ContentResourcesUrl": {
        "title": "URL",
        "description": "Content resources in URL format.",
        "type": "object",
        "required": [
          "description_markdown_url",
          "disclaimer_markdown_url",
          "refund_policy_markdown_url",
          "reissuance_policy_markdown_url",
          "terms_buyer_markdown_url",
          "terms_consumer_markdown_url",
          "redemption_instructions_markdown_url",
          "locale"
        ],
        "properties": {
          "description_markdown_url": {
            "type": "string",
            "format": "uri",
            "description": "A URL pointing to a markdown file that contains the description of the resource.",
            "examples": [
              "https://d2abcdef.cloudfront.net/resources/XYZ-US/description.md"
            ]
          },
          "disclaimer_markdown_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "A URL pointing to a markdown file that contains the disclaimer information.",
            "examples": [
              "https://d2abcdef.cloudfront.net/resources/XYZ-US/disclaimer_markdown.md"
            ]
          },
          "refund_policy_markdown_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "A URL pointing to a markdown file that outlines the refund policy, if applicable.",
            "examples": [
              "https://d2abcdef.cloudfront.net/resources/XYZ-US/refund_policy_markdown.md"
            ]
          },
          "reissuance_policy_markdown_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "A URL pointing to a markdown file that details the reissuance policy for the resource.",
            "examples": [
              "https://d2abcdef.cloudfront.net/resources/XYZ-US/reissuance_policy_markdown.md"
            ]
          },
          "terms_buyer_markdown_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "A URL pointing to a markdown file that contains the terms and conditions applicable to buyers.",
            "examples": [
              "https://d2abcdef.cloudfront.net/resources/XYZ-US/terms_buyer.md"
            ]
          },
          "terms_consumer_markdown_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "A URL pointing to a markdown file that contains the terms and conditions applicable to consumers.",
            "examples": [
              "https://d2abcdef.cloudfront.net/resources/XYZ-US/terms_consumer.md"
            ]
          },
          "redemption_instructions_markdown_url": {
            "type": ["string", "null"],
            "format": "uri",
            "description": "A URL pointing to a markdown file that provides instructions for redeeming the resource.",
            "examples": [
              "https://d2abcdef.cloudfront.net/resources/XYZ-US/redeem_markdown.md"
            ]
          },
          "locale": { "$ref": "#/components/schemas/ContentResourcesLocale" }
        }
      },
      "ContentResourcesMarkdown": {
        "title": "Markdown",
        "description": "Content resources in Markdown format.",
        "type": "object",
        "required": [
          "description_md",
          "disclaimer_md",
          "refund_policy_md",
          "reissuance_policy_md",
          "terms_buyer_md",
          "terms_consumer_md",
          "redemption_instructions_md",
          "locale"
        ],
        "properties": {
          "description_md": {
            "type": "string",
            "description": "Markdown content for the resource description."
          },
          "disclaimer_md": {
            "type": ["string", "null"],
            "description": "Markdown content for the disclaimer information."
          },
          "refund_policy_md": {
            "type": ["string", "null"],
            "description": "Markdown content outlining the refund policy, if applicable."
          },
          "reissuance_policy_md": {
            "type": ["string", "null"],
            "description": "Markdown content detailing the reissuance policy for the resource."
          },
          "terms_buyer_md": {
            "type": ["string", "null"],
            "description": "Markdown content containing terms and conditions applicable to buyers."
          },
          "terms_consumer_md": {
            "type": ["string", "null"],
            "description": "Markdown content containing terms and conditions applicable to consumers."
          },
          "redemption_instructions_md": {
            "type": ["string", "null"],
            "description": "Markdown instructions for redeeming the resource."
          },
          "locale": { "$ref": "#/components/schemas/ContentResourcesLocale" }
        }
      },
      "ContentResourcesHtml": {
        "title": "HTML",
        "description": "Content resources in HTML format.",
        "type": "object",
        "required": [
          "description_html",
          "disclaimer_html",
          "refund_policy_html",
          "reissuance_policy_html",
          "terms_buyer_html",
          "terms_consumer_html",
          "redemption_instructions_html",
          "locale"
        ],
        "properties": {
          "description_html": {
            "type": "string",
            "format": "html",
            "description": "HTML content for the resource description."
          },
          "disclaimer_html": {
            "type": ["string", "null"],
            "format": "html",
            "description": "HTML content for the disclaimer information."
          },
          "refund_policy_html": {
            "type": ["string", "null"],
            "format": "html",
            "description": "HTML content outlining the refund policy, if applicable."
          },
          "reissuance_policy_html": {
            "type": ["string", "null"],
            "format": "html",
            "description": "HTML content detailing the reissuance policy for the resource."
          },
          "terms_buyer_html": {
            "type": ["string", "null"],
            "format": "html",
            "description": "HTML content containing terms and conditions applicable to buyers."
          },
          "terms_consumer_html": {
            "type": ["string", "null"],
            "format": "html",
            "description": "HTML content containing terms and conditions applicable to consumers."
          },
          "redemption_instructions_html": {
            "type": ["string", "null"],
            "format": "html",
            "description": "HTML instructions for redeeming the resource."
          },
          "locale": { "$ref": "#/components/schemas/ContentResourcesLocale" }
        }
      }
    },
    "responses": {
      "InternalServerError": {
        "description": "Internal server error",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorResponse"
            }
          }
        }
      },
      "BadRequest": {
        "description": "Bad request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorResponse"
            }
          }
        }
      },
      "RateExceeded": {
        "description": "Rate limit exceeded",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorResponse"
            },
            "example": {
              "type": "rate_limit",
              "message": "You've exceeded the rate limit, please wait a short period and try again.",
              "help": "See https://developer.runa.io/rate-limits for details."
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Unauthorized",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorResponse"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Forbidden",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorResponse"
            }
          }
        }
      },
      "NotFound": {
        "description": "Not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiErrorResponse"
            }
          }
        }
      },
      "ValidationError": {
        "description": "Request failed validation",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ValidationErrorResponse"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "Your API key. See the [API key](/getting-started/api-key) page on details of how to generate and store your keys."
      }
    }
  },
  "security": [
    {
      "ApiKeyAuth": []
    }
  ]
}
