{
  "openapi": "3.0.3",
  "info": {
    "title": "NEXCODE Vouchers and ID Top-ups API",
    "version": "1.1.0",
    "description": "Purchase inventory vouchers or manual player ID top-ups. Examples are illustrative, not redeemable codes. No sandbox: accepted purchases debit the real wallet. See /api/docs for input, status polling, refund, replay and retention rules. Routing/proxy errors may not use the API JSON envelope."
  },
  "servers": [
    {
      "url": "https://nexcodesa.com/api/v1",
      "description": "Production HTTPS API; purchases debit the real wallet."
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "paths": {
    "/ping": {
      "get": {
        "operationId": "ping",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Ping"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "client": "Example client",
                    "server_time": "2026-09-21T00:00:00+00:00",
                    "rate_limit_per_minute": 60
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_token / invalid_token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "client_disabled / ip_not_allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited (error.retry_after_seconds)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/balance": {
      "get": {
        "operationId": "balance",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Balance"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "balance": 100,
                    "currency": "SAR"
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_token / invalid_token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "client_disabled / ip_not_allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited (error.retry_after_seconds)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "client_without_wallet / order_refused / request_in_progress / request_abandoned / idempotency_key_reused",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/products": {
      "get": {
        "operationId": "products",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Product"
                          }
                        },
                        "pagination": {
                          "$ref": "#/components/schemas/Pagination"
                        }
                      },
                      "required": [
                        "items",
                        "pagination"
                      ]
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "items": [
                      {
                        "id": 12,
                        "name": "Example game voucher",
                        "type": "voucher",
                        "currency": "SAR",
                        "merchant_reference": null,
                        "available_stock": 3,
                        "in_stock": true,
                        "price": 10,
                        "quantity_step": 1,
                        "sellable": true,
                        "variations": []
                      }
                    ],
                    "pagination": {
                      "page": 1,
                      "per_page": 50,
                      "total": 1,
                      "last_page": 1
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_token / invalid_token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "client_disabled / ip_not_allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited (error.retry_after_seconds)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "description": "Page number"
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Clamped by server to 1..100; default applies when omitted."
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Product name search"
          },
          {
            "name": "in_stock",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Use 1 or true to require some available codes on a product or active variation; this does not guarantee enough stock for quantity_step."
          }
        ]
      }
    },
    "/products/{product}": {
      "get": {
        "operationId": "product",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": 12,
                    "name": "Example game voucher",
                    "type": "voucher",
                    "currency": "SAR",
                    "merchant_reference": null,
                    "available_stock": 3,
                    "in_stock": true,
                    "price": 10,
                    "quantity_step": 1,
                    "sellable": true,
                    "variations": []
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_token / invalid_token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "client_disabled / ip_not_allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited (error.retry_after_seconds)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "product_not_found / product_reference_not_found / order_not_found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "product",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ]
      }
    },
    "/orders": {
      "get": {
        "operationId": "orders",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Order"
                          }
                        },
                        "pagination": {
                          "$ref": "#/components/schemas/Pagination"
                        }
                      },
                      "required": [
                        "items",
                        "pagination"
                      ]
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "items": [
                      {
                        "reference": "01K5A6B7C8D9E0F1G2H3J4K5M6",
                        "status": "completed",
                        "product_id": 12,
                        "variation_id": null,
                        "merchant_reference": null,
                        "quantity": 3,
                        "units": 3,
                        "units_per_sale": 1,
                        "unit_price": 10,
                        "total_price": 30,
                        "currency": "SAR",
                        "created_at": "2026-09-21T00:00:00+00:00",
                        "codes": [
                          {
                            "code": "EXAMPLE-CODE-001"
                          },
                          {
                            "code": "EXAMPLE-CODE-002"
                          },
                          {
                            "code": "EXAMPLE-CODE-003"
                          }
                        ]
                      }
                    ],
                    "pagination": {
                      "page": 1,
                      "per_page": 25,
                      "total": 1,
                      "last_page": 1
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_token / invalid_token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "client_disabled / ip_not_allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited (error.retry_after_seconds)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "description": "Page number"
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            },
            "description": "Clamped by server to 1..100; default applies when omitted."
          }
        ],
        "description": "Only orders purchased by this API client, newest first; no status, date or merchant order reference filters. Includes purchased codes."
      },
      "post": {
        "operationId": "purchase",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Order"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                },
                "examples": {
                  "voucher": {
                    "value": {
                      "success": true,
                      "data": {
                        "reference": "01K5A6B7C8D9E0F1G2H3J4K5M6",
                        "status": "completed",
                        "product_id": 12,
                        "variation_id": null,
                        "merchant_reference": null,
                        "quantity": 3,
                        "units": 3,
                        "units_per_sale": 1,
                        "unit_price": 10,
                        "total_price": 30,
                        "currency": "SAR",
                        "created_at": "2026-09-21T00:00:00+00:00",
                        "codes": [
                          {
                            "code": "EXAMPLE-CODE-001"
                          },
                          {
                            "code": "EXAMPLE-CODE-002"
                          },
                          {
                            "code": "EXAMPLE-CODE-003"
                          }
                        ]
                      }
                    }
                  },
                  "topup": {
                    "value": {
                      "success": true,
                      "data": {
                        "reference": "01K5A6B7C8D9E0F1G2H3J4K5M7",
                        "status": "pending",
                        "delivery_type": "top_up",
                        "system_product_id": 1,
                        "player_id": "001234567",
                        "quantity": 1,
                        "units": 1,
                        "units_per_sale": 1,
                        "unit_price": 25,
                        "total_price": 25,
                        "currency": "SAR",
                        "created_at": "2026-09-21T08:00:00+00:00",
                        "fulfilment_status": "processing",
                        "refunded": false,
                        "failure_reason": null,
                        "codes": []
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "Idempotent-Replay": {
                "description": "Present with value true only when replaying a stored success. Replayed HTTP status is also 201.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            }
          },
          "401": {
            "description": "missing_token / invalid_token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "client_disabled / ip_not_allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited (error.retry_after_seconds)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "idempotency_key_required / idempotency_key_too_long",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "product_not_found / product_reference_not_found / order_not_found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "client_without_wallet / order_refused / request_in_progress / request_abandoned / idempotency_key_reused",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "validation_failed / variation_mismatch / product_reference_ambiguous",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "server_error; outcome may be unknown. Retry using the same idempotency key and content.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "description": "Use a unique ASCII UUID per new purchase; reuse the same key and request on retries. Limit is 128 bytes. Scoped to this API client. Never reuse after retention cleanup."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Purchase"
              },
              "examples": {
                "by_id": {
                  "value": {
                    "product_id": 12,
                    "quantity": 3
                  }
                },
                "by_reference": {
                  "value": {
                    "merchant_reference": "PUBG-60",
                    "quantity": 3
                  }
                },
                "topup": {
                  "value": {
                    "delivery_type": "top_up",
                    "system_product_id": 1,
                    "player_id": "001234567"
                  }
                }
              }
            }
          }
        },
        "description": "Voucher mode synchronously delivers codes. top_up mode debits once, creates an administration fulfilment order and returns pending while operators work. Poll GET /orders/{reference} with the same API client for current status and refunded. Internal top-up codes are never exposed. Selected eligible top-up products reach Telegram through platform settings. No customer webhooks. A replay returns the ORIGINAL creation response; use GET for current state."
      }
    },
    "/orders/{reference}": {
      "get": {
        "operationId": "order",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/Order"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "reference": "01K5A6B7C8D9E0F1G2H3J4K5M6",
                    "status": "completed",
                    "product_id": 12,
                    "variation_id": null,
                    "merchant_reference": null,
                    "quantity": 3,
                    "units": 3,
                    "units_per_sale": 1,
                    "unit_price": 10,
                    "total_price": 30,
                    "currency": "SAR",
                    "created_at": "2026-09-21T00:00:00+00:00",
                    "codes": [
                      {
                        "code": "EXAMPLE-CODE-001"
                      },
                      {
                        "code": "EXAMPLE-CODE-002"
                      },
                      {
                        "code": "EXAMPLE-CODE-003"
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_token / invalid_token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "client_disabled / ip_not_allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited (error.retry_after_seconds)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "product_not_found / product_reference_not_found / order_not_found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "description": "Only this API client can read the order, including when two clients belong to the same account."
      }
    },
    "/topup-products": {
      "get": {
        "operationId": "topupProducts",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "items": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/TopupProduct"
                          }
                        },
                        "pagination": {
                          "$ref": "#/components/schemas/Pagination"
                        }
                      },
                      "required": [
                        "items",
                        "pagination"
                      ]
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "items": [
                      {
                        "id": 1,
                        "name": "Example ID top-up package",
                        "category": "Example game",
                        "delivery_type": "top_up",
                        "price": 25,
                        "currency": "SAR",
                        "available_stock": 3,
                        "sellable": true,
                        "quantity_step": 1,
                        "max_quantity": 1,
                        "fields": []
                      }
                    ],
                    "pagination": {
                      "page": 1,
                      "per_page": 50,
                      "total": 1,
                      "last_page": 1
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_token / invalid_token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "client_disabled / ip_not_allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited (error.retry_after_seconds)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            },
            "description": "Page number"
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Clamped by server to 1..100; default applies when omitted."
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Product name search"
          }
        ],
        "description": "Manual ID top-up catalogue; active internal supplier mappings only. available_stock counts packages and is not a reservation. Product/category deactivation omits it from lists and returns 404 on detail."
      }
    },
    "/topup-products/{product}": {
      "get": {
        "operationId": "topupProduct",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/TopupProduct"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                },
                "example": {
                  "success": true,
                  "data": {
                    "id": 1,
                    "name": "Example ID top-up package",
                    "category": "Example game",
                    "delivery_type": "top_up",
                    "price": 25,
                    "currency": "SAR",
                    "available_stock": 3,
                    "sellable": true,
                    "quantity_step": 1,
                    "max_quantity": 1,
                    "fields": []
                  }
                }
              }
            }
          },
          "401": {
            "description": "missing_token / invalid_token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "client_disabled / ip_not_allowed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "rate_limited (error.retry_after_seconds)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "product_not_found / product_reference_not_found / order_not_found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "product",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          }
        ],
        "description": "Manual ID top-up catalogue; active internal supplier mappings only. available_stock counts packages and is not a reservation. Product/category deactivation omits it from lists and returns 404 on detail."
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Secret issued through the merchant API page. Send from your server, never browser JavaScript."
      }
    },
    "schemas": {
      "Pagination": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer"
          },
          "per_page": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          },
          "last_page": {
            "type": "integer"
          }
        },
        "required": [
          "page",
          "per_page",
          "total",
          "last_page"
        ]
      },
      "Variation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "merchant_reference": {
            "type": "string",
            "nullable": true
          },
          "available_stock": {
            "type": "integer",
            "minimum": 0
          },
          "price": {
            "type": "number",
            "nullable": true
          },
          "quantity_step": {
            "type": "integer",
            "minimum": 1
          },
          "sellable": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "name",
          "merchant_reference",
          "available_stock",
          "price",
          "quantity_step",
          "sellable"
        ]
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "nullable": true,
            "enum": [
              "voucher",
              "top_up",
              null
            ]
          },
          "currency": {
            "type": "string"
          },
          "merchant_reference": {
            "type": "string",
            "nullable": true
          },
          "available_stock": {
            "type": "integer",
            "minimum": 0
          },
          "in_stock": {
            "type": "boolean"
          },
          "price": {
            "type": "number",
            "nullable": true
          },
          "quantity_step": {
            "type": "integer",
            "minimum": 1
          },
          "sellable": {
            "type": "boolean"
          },
          "variations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Variation"
            }
          }
        },
        "required": [
          "id",
          "name",
          "type",
          "currency",
          "merchant_reference",
          "available_stock",
          "in_stock",
          "price",
          "quantity_step",
          "sellable",
          "variations"
        ]
      },
      "Order": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/VoucherOrder"
          },
          {
            "$ref": "#/components/schemas/TopupOrder"
          }
        ]
      },
      "Code": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "serial_number": {
            "type": "string"
          },
          "pin_code": {
            "type": "string"
          }
        },
        "required": [
          "code"
        ]
      },
      "Ping": {
        "type": "object",
        "properties": {
          "client": {
            "type": "string"
          },
          "server_time": {
            "type": "string",
            "format": "date-time"
          },
          "rate_limit_per_minute": {
            "type": "integer"
          }
        },
        "required": [
          "client",
          "server_time",
          "rate_limit_per_minute"
        ]
      },
      "Balance": {
        "type": "object",
        "properties": {
          "balance": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          }
        },
        "required": [
          "balance",
          "currency"
        ]
      },
      "Error": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "reason": {
                "type": "string",
                "nullable": true
              },
              "fields": {
                "type": "object",
                "additionalProperties": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              },
              "reference": {
                "type": "string"
              },
              "merchant_reference": {
                "type": "string"
              },
              "retry_after_seconds": {
                "type": "integer"
              },
              "recovery": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "success",
          "error"
        ]
      },
      "Purchase": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/VoucherPurchase"
          },
          {
            "$ref": "#/components/schemas/TopupPurchase"
          }
        ]
      },
      "VoucherOrder": {
        "type": "object",
        "properties": {
          "reference": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "completed",
              "failed"
            ]
          },
          "product_id": {
            "type": "integer"
          },
          "variation_id": {
            "type": "integer",
            "nullable": true
          },
          "merchant_reference": {
            "type": "string",
            "nullable": true
          },
          "quantity": {
            "type": "integer"
          },
          "units": {
            "type": "integer"
          },
          "units_per_sale": {
            "type": "integer"
          },
          "unit_price": {
            "type": "number"
          },
          "total_price": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "codes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Code"
            }
          }
        },
        "required": [
          "reference",
          "status",
          "product_id",
          "variation_id",
          "merchant_reference",
          "quantity",
          "units",
          "units_per_sale",
          "unit_price",
          "total_price",
          "currency",
          "created_at",
          "codes"
        ]
      },
      "VoucherPurchase": {
        "type": "object",
        "properties": {
          "product_id": {
            "type": "integer",
            "description": "Supplier product ID returned by GET /products, not a storefront system product ID."
          },
          "merchant_reference": {
            "type": "string",
            "maxLength": 64,
            "description": "Your mapped product reference, not your order reference. Use instead of product_id. Starts with a Unicode letter or number; subsequent characters may be Unicode letters, numbers, space, dot, underscore, hyphen, slash, colon or hash."
          },
          "variation_id": {
            "type": "integer",
            "nullable": true,
            "description": "Must belong to product_id. With merchant_reference, omit it or send the exact mapped variation."
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "description": "Number of codes; must be a multiple of quantity_step."
          },
          "delivery_type": {
            "type": "string",
            "enum": [
              "voucher"
            ]
          }
        },
        "required": [
          "quantity"
        ],
        "oneOf": [
          {
            "required": [
              "product_id"
            ],
            "not": {
              "required": [
                "merchant_reference"
              ]
            }
          },
          {
            "required": [
              "merchant_reference"
            ],
            "not": {
              "required": [
                "product_id"
              ]
            }
          }
        ],
        "description": "Synchronous voucher purchase. Omit delivery_type or use voucher. Never send player_id, system_product_id or fields.",
        "not": {
          "anyOf": [
            {
              "required": [
                "system_product_id"
              ]
            },
            {
              "required": [
                "player_id"
              ]
            },
            {
              "required": [
                "fields"
              ]
            }
          ]
        }
      },
      "TopupField": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "text",
              "number",
              "dropdown"
            ]
          },
          "required": {
            "type": "boolean"
          },
          "options": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "string"
                },
                "label": {
                  "type": "string",
                  "nullable": true
                }
              },
              "required": [
                "value",
                "label"
              ]
            }
          }
        },
        "required": [
          "id",
          "name",
          "label",
          "type",
          "required",
          "options"
        ]
      },
      "TopupProduct": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "category": {
            "type": "string",
            "nullable": true
          },
          "delivery_type": {
            "type": "string",
            "enum": [
              "top_up"
            ]
          },
          "price": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          },
          "available_stock": {
            "type": "integer",
            "nullable": true
          },
          "sellable": {
            "type": "boolean"
          },
          "quantity_step": {
            "type": "integer",
            "enum": [
              1
            ]
          },
          "max_quantity": {
            "type": "integer",
            "enum": [
              1
            ]
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TopupField"
            }
          }
        },
        "required": [
          "id",
          "name",
          "category",
          "delivery_type",
          "price",
          "currency",
          "available_stock",
          "sellable",
          "quantity_step",
          "max_quantity",
          "fields"
        ]
      },
      "TopupPurchase": {
        "type": "object",
        "properties": {
          "delivery_type": {
            "type": "string",
            "enum": [
              "top_up"
            ]
          },
          "system_product_id": {
            "type": "integer",
            "description": "ID from /topup-products, not /products."
          },
          "player_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[A-Za-z0-9_-]{1,64}$",
            "description": "String, preserve leading zeroes."
          },
          "quantity": {
            "type": "integer",
            "enum": [
              1
            ],
            "default": 1
          },
          "fields": {
            "type": "object",
            "maxProperties": 30,
            "additionalProperties": {
              "type": "string",
              "maxLength": 255,
              "nullable": true
            },
            "description": "Additional configured field IDs mapped to string values; omit the player identifier here."
          }
        },
        "required": [
          "delivery_type",
          "system_product_id",
          "player_id"
        ],
        "description": "One package per player per request. product_id, variation_id and merchant_reference are prohibited.",
        "not": {
          "anyOf": [
            {
              "required": [
                "product_id"
              ]
            },
            {
              "required": [
                "variation_id"
              ]
            },
            {
              "required": [
                "merchant_reference"
              ]
            }
          ]
        }
      },
      "TopupOrder": {
        "type": "object",
        "properties": {
          "reference": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "completed",
              "failed"
            ]
          },
          "delivery_type": {
            "type": "string",
            "enum": [
              "top_up"
            ]
          },
          "system_product_id": {
            "type": "integer"
          },
          "player_id": {
            "type": "string"
          },
          "quantity": {
            "type": "integer",
            "enum": [
              1
            ]
          },
          "units": {
            "type": "integer",
            "enum": [
              1
            ]
          },
          "units_per_sale": {
            "type": "integer",
            "enum": [
              1
            ]
          },
          "unit_price": {
            "type": "number"
          },
          "total_price": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "fulfilment_status": {
            "type": "string",
            "enum": [
              "pending",
              "pending_review",
              "processing",
              "completed",
              "failed"
            ]
          },
          "refunded": {
            "type": "boolean"
          },
          "failure_reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "wrong_id",
              "no_stock",
              "fulfilment_failed",
              null
            ]
          },
          "codes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Code"
            },
            "maxItems": 0
          }
        },
        "required": [
          "reference",
          "status",
          "delivery_type",
          "system_product_id",
          "player_id",
          "quantity",
          "units",
          "units_per_sale",
          "unit_price",
          "total_price",
          "currency",
          "created_at",
          "fulfilment_status",
          "refunded",
          "failure_reason",
          "codes"
        ]
      }
    }
  }
}
