Skip to content

Makseb for developers · API v1

Your business.
Connected.

Build the experience you imagine.
Keep your products, orders and tickets in sync with Makseb.

Scoped credentialsIsolated sandboxVersioned endpoints

Try it now · No account needed

A public demo. Ready to use.

Read fixed, synthetic zoo data with this public token. It is safe to share because it grants no access to business data, payments, webhooks or gate operation.

Public demo tokenmk_demo_public_readonly

This is a public example credential, not a secret key.

Demo base URLhttps://sandbox-api.makseb.io/demo/v1

GET /branches · GET /products · GET /services

Read sample zone tickets
curl https://sandbox-api.makseb.io/demo/v1/services \
  -H 'Authorization: Bearer mk_demo_public_readonly'

Demo responses contain demo: true. Only the three listed read endpoints are supported, with no query parameters. Writes return 405 demo_read_only; the token is rejected by the real sandbox and production APIs. The sample data never changes.

For orders, inventory changes, webhooks and gate-scan testing, create your own isolated sandbox credentials below. A shared write secret would let strangers alter one another’s test data.

01 / Get started

One API. Your whole operation.

Sign in to your Makseb business and open Settings → Developers. Select Sandbox, select the branches and permissions you need, verify with an email or SMS code, then choose Create integration and key. Save the secret when it is shown; keep it on your server. This setup is self-service and does not require contacting Makseb.

Sandboxhttps://sandbox-api.makseb.io

Build and test with isolated data.

Productionhttps://api.makseb.io

Connect to your live business.

Your first request
curl https://sandbox-api.makseb.io/v1/branches \
  -H 'Authorization: Bearer YOUR_TEST_SECRET'

Send Authorization: Bearer YOUR_SECRET with authenticated requests. Never place a business secret in a browser or mobile app. Test and live keys cannot be used interchangeably.

02 / API reference

Everything you can connect.

Explore the supported operations. Request and response schemas below come directly from the versioned API contract.

31 endpoints

GET/v1/branchesList authorized branches

List authorized branches

Required scope: branches:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "List authorized branches",
  "description": "Required scope: branches:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Page"
              },
              {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Branch"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 50
      },
      "description": "Maximum rows per page."
    },
    {
      "name": "after",
      "in": "query",
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "description": "The next_after value from the previous page."
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/productsList products

List products

Required scope: catalog:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "List products",
  "description": "Required scope: catalog:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Page"
              },
              {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/CatalogItem"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 50
      },
      "description": "Maximum rows per page."
    },
    {
      "name": "after",
      "in": "query",
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "description": "The next_after value from the previous page."
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/servicesList services

List services

Required scope: catalog:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "List services",
  "description": "Required scope: catalog:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Page"
              },
              {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/CatalogItem"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 50
      },
      "description": "Maximum rows per page."
    },
    {
      "name": "after",
      "in": "query",
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "description": "The next_after value from the previous page."
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/inventoryRead inventory quantities

Read inventory quantities

Required scope: inventory:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Read inventory quantities",
  "description": "Required scope: inventory:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Page"
              },
              {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/InventoryItem"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 50
      },
      "description": "Maximum rows per page."
    },
    {
      "name": "after",
      "in": "query",
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "description": "The next_after value from the previous page."
    }
  ]
}
Look up referenced data schemas ↓
POST/v1/inventory/adjustmentsRecord a stock adjustment

Record a stock adjustment

Required scope: inventory:write. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Record a stock adjustment",
  "description": "Required scope: inventory:write. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "201": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "branch_id": {
                "type": "string",
                "format": "uuid"
              },
              "inventory_item_id": {
                "type": "string",
                "format": "uuid"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "Idempotency-Key",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "minLength": 8,
        "maxLength": 128
      },
      "description": "Generate once per operation and reuse unchanged for retries."
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "required": [
            "branch_id",
            "inventory_item_id",
            "quantity_delta",
            "movement_type",
            "reason"
          ],
          "properties": {
            "branch_id": {
              "type": "string",
              "format": "uuid"
            },
            "inventory_item_id": {
              "type": "string",
              "format": "uuid"
            },
            "variant_id": {
              "type": "string",
              "format": "uuid"
            },
            "quantity_delta": {
              "type": "number",
              "not": {
                "const": 0
              }
            },
            "movement_type": {
              "enum": [
                "adjust_expired",
                "adjust_damaged",
                "adjust_lost",
                "adjust_found",
                "adjust_internal_use",
                "adjust_correction"
              ]
            },
            "reason": {
              "type": "string",
              "minLength": 3
            }
          }
        }
      }
    }
  }
}
Look up referenced data schemas ↓
GET/v1/ordersList orders

List orders

Required scope: orders:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "List orders",
  "description": "Required scope: orders:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Page"
              },
              {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Order"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 50
      },
      "description": "Maximum rows per page."
    },
    {
      "name": "after",
      "in": "query",
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "description": "The next_after value from the previous page."
    }
  ]
}
Look up referenced data schemas ↓
POST/v1/ordersCreate a customer order using server prices

Create a customer order using server prices

Required scope: orders:write. All results are restricted to the integration business and branches. For age-priced tickets, add one service line per visitor category using that price record's variant_id. Keep quantity at 1 and set booking.party_size to the number of visitors in that category. Each visitor receives a separate QR after payment.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Create a customer order using server prices",
  "description": "Required scope: orders:write. All results are restricted to the integration business and branches. For age-priced tickets, add one service line per visitor category using that price record's variant_id. Keep quantity at 1 and set booking.party_size to the number of visitors in that category. Each visitor receives a separate QR after payment.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "201": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CreatedOrder"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "Idempotency-Key",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "minLength": 8,
        "maxLength": 128
      },
      "description": "Generate once per operation and reuse unchanged for retries."
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/CreateOrder"
        }
      }
    }
  }
}
Look up referenced data schemas ↓
GET/v1/orders/{id}Retrieve an order

Retrieve an order

Required scope: orders:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Retrieve an order",
  "description": "Required scope: orders:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Order"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/bookingsList bookings

List bookings

Required scope: bookings:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "List bookings",
  "description": "Required scope: bookings:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Page"
              },
              {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Booking"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 50
      },
      "description": "Maximum rows per page."
    },
    {
      "name": "after",
      "in": "query",
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "description": "The next_after value from the previous page."
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/customersList minimal customer identities

List minimal customer identities

Required scope: customers:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "List minimal customer identities",
  "description": "Required scope: customers:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Page"
              },
              {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 50
      },
      "description": "Maximum rows per page."
    },
    {
      "name": "after",
      "in": "query",
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "description": "The next_after value from the previous page."
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/paymentsList recorded payments and actual gateway fees

List recorded payments and actual gateway fees

Required scope: financials:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "List recorded payments and actual gateway fees",
  "description": "Required scope: financials:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Page"
              },
              {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Payment"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 50
      },
      "description": "Maximum rows per page."
    },
    {
      "name": "after",
      "in": "query",
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "description": "The next_after value from the previous page."
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/tickets/{id}Retrieve ticket entitlements

Retrieve ticket entitlements

Required scope: tickets:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Retrieve ticket entitlements",
  "description": "Required scope: tickets:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Ticket"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ]
}
Look up referenced data schemas ↓
POST/v1/services/{id}/availabilityCheck requested service times

Check requested service times

Required scope: catalog:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Check requested service times",
  "description": "Required scope: catalog:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "booking_time": {
                      "type": "string"
                    },
                    "remaining_capacity": {
                      "type": "integer"
                    },
                    "resource_available": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "required": [
            "date",
            "times"
          ],
          "properties": {
            "date": {
              "type": "string",
              "format": "date",
              "description": "Date in the branch time zone."
            },
            "times": {
              "type": "array",
              "minItems": 1,
              "maxItems": 96,
              "items": {
                "type": "string",
                "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$"
              }
            },
            "days": {
              "type": "integer",
              "minimum": 1
            },
            "hours": {
              "type": "integer",
              "minimum": 1
            },
            "resource_id": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      }
    }
  }
}
Look up referenced data schemas ↓
POST/v1/customer-ticketsRetrieve or fulfill tickets using a signed-receipt capability

Retrieve or fulfill tickets using a signed-receipt capability

No business API key is needed. The receipt token authorizes only its own order. Paid fulfillment is idempotent; refunded orders require business assistance.

Authentication: Operation-specific capability; see request schema

Request and response contract
{
  "summary": "Retrieve or fulfill tickets using a signed-receipt capability",
  "description": "No business API key is needed. The receipt token authorizes only its own order. Paid fulfillment is idempotent; refunded orders require business assistance.",
  "security": [],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "required": [
            "receipt_token"
          ],
          "properties": {
            "receipt_token": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{32}$"
            },
            "offset": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        }
      }
    }
  },
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Ticket"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "qr_code": {
                          "type": "string"
                        },
                        "timezone": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                }
              },
              "has_more": {
                "type": "boolean"
              },
              "next_offset": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "total": {
                "type": "integer"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  }
}
Look up referenced data schemas ↓
POST/v1/customer-orders/statusRead current order and payment status using its capability

Read current order and payment status using its capability

Use branch_id and placement_key returned at creation. A browser redirect is not proof of payment.

Authentication: Operation-specific capability; see request schema

Request and response contract
{
  "summary": "Read current order and payment status using its capability",
  "description": "Use branch_id and placement_key returned at creation. A browser redirect is not proof of payment.",
  "security": [],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "$ref": "#/components/schemas/OrderCapability"
        }
      }
    }
  },
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "payment_status": {
                "type": "string"
              },
              "is_paid": {
                "type": "boolean"
              },
              "total_minor": {
                "type": "integer"
              },
              "paid_minor": {
                "type": "integer"
              },
              "remaining_minor": {
                "type": "integer"
              },
              "currency_code": {
                "type": "string"
              },
              "receipt_token": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "items": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  }
}
Look up referenced data schemas ↓
POST/v1/customer-orders/checkoutStart hosted checkout for a customer order

Start hosted checkout for a customer order

Available when the environment has an enabled payment gateway. The sandbox preview may report checkout_unavailable. No raw card details are accepted.

Authentication: Operation-specific capability; see request schema

Request and response contract
{
  "summary": "Start hosted checkout for a customer order",
  "description": "Available when the environment has an enabled payment gateway. The sandbox preview may report checkout_unavailable. No raw card details are accepted.",
  "security": [],
  "parameters": [
    {
      "name": "Idempotency-Key",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "minLength": 8,
        "maxLength": 128
      },
      "description": "Generate once per operation and reuse unchanged for retries."
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "allOf": [
            {
              "$ref": "#/components/schemas/OrderCapability"
            },
            {
              "type": "object",
              "properties": {
                "customer": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "email": {
                      "type": "string",
                      "format": "email"
                    },
                    "phone": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          ]
        }
      }
    }
  },
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "checkout_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri"
              },
              "status_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  }
}
Look up referenced data schemas ↓
POST/v1/ticket-validationsCheck a QR without consuming entry

Check a QR without consuming entry

Required scope: access:validate. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Check a QR without consuming entry",
  "description": "Required scope: access:validate. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Validation"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Scan"
            },
            {
              "required": [
                "qr_code"
              ]
            }
          ]
        }
      }
    }
  }
}
Look up referenced data schemas ↓
POST/v1/access-attemptsAuthorize and consume a zone entry

Authorize and consume a zone entry

Required scope: access:redeem. All results are restricted to the integration business and branches. Main entrances start visits, main exits end them, and zone scanners enforce the visitor ticket areas and remaining allowances. Configure each scanner role in API integrations. A new physical scan needs a new Idempotency-Key; retries reuse the original key. Actuate each access_attempt_id at most once and before actuation_expires_at.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Authorize and consume a zone entry",
  "description": "Required scope: access:redeem. All results are restricted to the integration business and branches. Main entrances start visits, main exits end them, and zone scanners enforce the visitor ticket areas and remaining allowances. Configure each scanner role in API integrations. A new physical scan needs a new Idempotency-Key; retries reuse the original key. Actuate each access_attempt_id at most once and before actuation_expires_at.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/AccessDecision"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "Idempotency-Key",
      "in": "header",
      "required": true,
      "schema": {
        "type": "string",
        "minLength": 8,
        "maxLength": 128
      },
      "description": "Generate once for a physical scan. Reuse exactly for retries; never reuse for another scan."
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "allOf": [
            {
              "$ref": "#/components/schemas/Scan"
            },
            {
              "required": [
                "qr_code",
                "gate_id",
                "date_time"
              ]
            }
          ]
        }
      }
    }
  }
}
Look up referenced data schemas ↓
GET/v1/access-attempts/{id}Read historical decision; never actuate from this response

Read historical decision; never actuate from this response

Required scope: access:redeem. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Read historical decision; never actuate from this response",
  "description": "Required scope: access:redeem. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "decision": {
                "$ref": "#/components/schemas/AccessDecision"
              },
              "actuation_allowed": {
                "const": false
              },
              "decided_at": {
                "type": "string",
                "format": "date-time"
              },
              "passage_confirmed_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ]
}
Look up referenced data schemas ↓
POST/v1/access-attempts/{id}/confirmationRecord gate opening or confirmed passage

Record gate opening or confirmed passage

Required scope: access:confirm. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Record gate opening or confirmed passage",
  "description": "Required scope: access:confirm. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "access_attempt_id": {
                "type": "string",
                "format": "uuid"
              },
              "gate_opened_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "passage_confirmed_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ],
  "requestBody": {
    "required": true,
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "required": [
            "event"
          ],
          "properties": {
            "event": {
              "enum": [
                "gate_opened",
                "passage_confirmed"
              ]
            }
          }
        }
      }
    }
  }
}
Look up referenced data schemas ↓
GET/v1/changesRead authorized business changes

Read authorized business changes

Requires changes:read and the read scope of each resource. Captures catalog, inventory, orders, bookings, customers, financial records, tickets and access events. Results follow publication sequence; webhooks may arrive out of order. Rebuild mirrors after permissions change.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Read authorized business changes",
  "description": "Requires changes:read and the read scope of each resource. Captures catalog, inventory, orders, bookings, customers, financial records, tickets and access events. Results follow publication sequence; webhooks may arrive out of order. Rebuild mirrors after permissions change.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Event"
                }
              },
              "has_more": {
                "type": "boolean"
              },
              "next_sequence": {
                "type": "integer"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "410": {
      "description": "Cursor expired. Capture a new synchronization cursor and rebuild the snapshot. Changes are retained for 90 days.",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 50
      },
      "description": "Maximum rows per page."
    },
    {
      "name": "sequence",
      "in": "query",
      "schema": {
        "type": "integer",
        "minimum": 0,
        "default": 0
      },
      "description": "next_sequence from the last applied page, or the initial synchronization cursor."
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/branches/{id}Read one branche

Read one branche

Required scope: branches:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Read one branche",
  "description": "Required scope: branches:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Branch"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/products/{id}Read one product

Read one product

Required scope: catalog:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Read one product",
  "description": "Required scope: catalog:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CatalogItem"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/services/{id}Read one service

Read one service

Required scope: catalog:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Read one service",
  "description": "Required scope: catalog:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CatalogItem"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/inventory/{id}Read one inventory

Read one inventory

Required scope: inventory:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Read one inventory",
  "description": "Required scope: inventory:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/InventoryItem"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/bookings/{id}Read one booking

Read one booking

Required scope: bookings:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Read one booking",
  "description": "Required scope: bookings:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Booking"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/customers/{id}Read one customer

Read one customer

Required scope: customers:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Read one customer",
  "description": "Required scope: customers:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Customer"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/payments/{id}Read one payment

Read one payment

Required scope: financials:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Read one payment",
  "description": "Required scope: financials:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Payment"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/refunds/{id}Read one refund

Read one refund

Required scope: financials:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Read one refund",
  "description": "Required scope: financials:read. Returns current state within the integration business and branch permissions. Unavailable or unauthorized identifiers return 404.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Refund"
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "id",
      "in": "path",
      "required": true,
      "schema": {
        "type": "string",
        "format": "uuid"
      }
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/refundsList recorded refunds

List recorded refunds

Required scope: financials:read. All results are restricted to the integration business and branches.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "List recorded refunds",
  "description": "Required scope: financials:read. All results are restricted to the integration business and branches.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Page"
              },
              {
                "type": "object",
                "properties": {
                  "data": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/Refund"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  },
  "parameters": [
    {
      "name": "limit",
      "in": "query",
      "schema": {
        "type": "integer",
        "minimum": 1,
        "maximum": 100,
        "default": 50
      },
      "description": "Maximum rows per page."
    },
    {
      "name": "after",
      "in": "query",
      "schema": {
        "type": "string",
        "format": "uuid"
      },
      "description": "The next_after value from the previous page."
    }
  ]
}
Look up referenced data schemas ↓
GET/v1/sync/startCapture a synchronization cursor

Capture a synchronization cursor

Requires changes:read. Capture before reading snapshot pages, then apply changes after this sequence. This is not a transactionally frozen snapshot.

Authentication: Scoped business API key

Request and response contract
{
  "summary": "Capture a synchronization cursor",
  "description": "Requires changes:read. Capture before reading snapshot pages, then apply changes after this sequence. This is not a transactionally frozen snapshot.",
  "security": [
    {
      "ApiKey": []
    }
  ],
  "responses": {
    "200": {
      "description": "Successful response",
      "content": {
        "application/json": {
          "schema": {
            "type": "object",
            "properties": {
              "sequence": {
                "type": "integer"
              },
              "captured_at": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      }
    },
    "400": {
      "description": "Invalid request",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "401": {
      "description": "Invalid or expired credential",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "403": {
      "description": "Scope, gate or branch not authorized",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "404": {
      "description": "Resource unavailable",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "409": {
      "description": "Conflict",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "413": {
      "description": "Body exceeds 32 KiB",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "415": {
      "description": "JSON required",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "429": {
      "description": "Rate limit; honor Retry-After",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    },
    "503": {
      "description": "Service unavailable; do not open a gate",
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/Error"
          }
        }
      }
    }
  }
}
Look up referenced data schemas ↓

03 / Integration guides

Build with confidence.

The operational details that keep your integration reliable, from gate scans to synchronized inventory.

1. Create an integration

Open Settings → Developers → API integrations. Choose Sandbox or Live, name the integration, and select its branches and permissions. Confirm your identity with an email or SMS code, then select Create integration and key. Save the secret on your server.

For ticket scanners, select allowed gates in the same form or use Connect a gate or scanner. Link each scanner to a zone already saved in the service editor. Zone IDs are permanent UUIDs: renaming an area does not change its ID or disconnect scanners. The gate identifier is the value sent as gate_id.

Use Edit permissions and access on an existing integration to change its access without replacing its keys. Changes take effect on subsequent API requests.

2. Keep the secret on your server

Send the key in the Authorization bearer header. Do not embed it in an iOS app or browser. Test and live credentials are isolated. The UUID shown on the integration card is its public identifier and does not grant access.

Ticket admission

curl https://sandbox-api.makseb.io/v1/access-attempts \
  -H 'Authorization: Bearer YOUR_TEST_SECRET' \
  -H 'Idempotency-Key: ONE_ID_PER_PHYSICAL_SCAN' \
  -H 'Content-Type: application/json' \
  --data '{"qr_code":"TICKET_QR","gate_id":"GATE_ID","date_time":"2026-09-14T12:00:00Z"}'

Each visitor has an individual opaque QR code. One order can contain multiple visitor tickets; the receipt QR is not an admission ticket. Scanners send the QR and gate ID, not a product or service ID. A venue entrance can authorize new services without controller changes. A consumed simple ticket reports ticket_consumed: true; the validation itself still reports consumed: false on a general validation; use the gate-specific decision to decide whether to open.

Configure each scanner as a main entrance, main exit, zone entrance or zone exit in API integrations. An entrance scan starts a visit. An exit scan ends it. With the default single-entry policy, a ticket cannot enter the park again after exit. Owners can allow re-entry while the ticket remains valid.

Zone access requires an included zone and, when entry tracking is enabled, an active visit at that location. Zones can have a finite entry allowance or unlimited visits while inside. Unlimited balances are returned as null with unlimited_inside: true.

Use POST /v1/access-attempts to authorize a physical scan. Create one Idempotency-Key per physical attempt; reuse it with the same body only for retries. Open at most once per returned access_attempt_id and before actuation_expires_at. The actuation window is 30 seconds. Never open on an HTTP error, a denied or expired decision, or a historical lookup. Report passage confirmation when supported.

Validation never consumes an entry or promises a later admission. A check without gate_id reports general ticket validity, with gate_eligible set to null. Supply a gate ID to check eligibility at that gate.

Presence is based on recorded scans. Exit scanners must report departures for zone access to stop promptly. A QR identifies a visitor ticket, not a verified human identity.

Configure multiple ticket zones

Business owners manage areas in the service editor: name, photo, description and entry rules. Zone UUIDs are permanent and survive renaming or replacing a photo. Each ticket option can include every configured area or only selected areas.

Developers connect scanners in API integrations and copy the configured gate identifier into the controller. For a main entrance or exit, select an area belonging to that park location; the server checks the location rather than requiring that particular area in the ticket. Zone scanners check their specific zone.

Never derive identifiers from display names. Read ticket_access, ticket_options and ticket_rules from the catalog API. Service areas describe what can be offered; the ticket option selected at purchase determines actual visitor entitlements. Renaming areas updates presentation, while already-sold ticket allowances remain unchanged.

Zone entry, exit and capacity

Connect two scanners to each physical zone: an entry gate and an exit gate. Configure their direction in API integrations. Both call POST /v1/access-attempts with the visitor QR, their own gate_id and date_time. Never send a product ID or an occupancy count. The server owns gate direction, ticket rights and available places.

For an entry, Makseb atomically checks ticket validity, included zones, entry allowance and the live zone limit. A successful decision reserves one place and consumes one entry only when the service has a finite entry allowance. A full zone returns HTTP 200 with valid: false, status: access_failed and reason: zone_full. It consumes nothing. Try a new physical scan with a new idempotency key after a place becomes available.

An authorized exit scan records the departure and frees exactly one place. Repeated exit scans return not_inside_zone and never decrease the count twice. An entry scan while already inside returns already_inside_zone. A visitor recorded inside may exit even after their ticket expires or is revoked. Exit never restores a consumed entry allowance.

Responses include zone_capacity, zone_occupied, zone_available, inside_zone and zone_sequence. Capacity is shared across all products, packages and gates linked to that zone. Counts in a response are a snapshot; only a new access attempt can reserve a place. Validation is read-only and never reserves capacity.

Use one idempotency key per physical scan and reuse it only when retrying the identical request. Open once per access_attempt_id, only on valid: true and before actuation_expires_at. Never reopen from a historical lookup. An approval from before a later zone entry or exit becomes invalid. Send gate_opened and passage_confirmed events through the confirmation endpoint when supported.

Occupancy is based on authorized scans, not a physical sensor count. Entry approvals hold a place even if the visitor does not pass. Controllers must not report an exit before the visitor is departing. Do not automatically clear occupancy when approvals or tickets expire, or at midnight. Staff must reconcile missed scans against the actual zone. A park exit does not silently clear recorded zone presence; zone exit scanners must report departures.

Zoo and theme-park booking tickets are valid from midnight on the selected date until the next midnight in the branch timezone, rather than for a timed session or 24 hours from the first scan. Scheduled event tickets retain their scheduled validity. Outside the valid date, entry is refused, but recorded visitors can still exit.

For date-based park bookings, send the selected date and 00:00 as the technical booking time. For POST /v1/services/{id}/availability, use times: ["00:00"]. The response describes whether the date can be booked, not available physical zone places. A booking does not reserve a place inside a zone.

Owners can correct missed scans in the service editor under Correct missed scans. Pause entry, verify the zone is physically empty and record a reason. Corrections are audited, refuse stale presence revisions and invalidate older zone approvals. They do not restore ticket entry allowances.

POST /v1/access-attempts
Authorization: Bearer YOUR_SECRET_KEY
Idempotency-Key: NEW_UNIQUE_PHYSICAL_SCAN_ID

{"qr_code":"VISITOR_QR","gate_id":"ZONE_A_ENTRY","date_time":"2026-09-14T10:00:00Z"}

{"valid":true,"status":"access_granted","zone_capacity":20,"zone_occupied":20,"zone_available":0,"inside_zone":true}

The example response is abbreviated. The real response includes the access attempt ID and expiry required to operate the door. An inside scanner sends its separately configured exit gate ID with a new scan ID. Never let a customer choose entry versus exit in the payload.

Money & accounting

Monetary fields ending in _minor use the currency's minor unit: OMR 12.500 is 12500. Null gateway fees and fee VAT are unknown, not zero. Payment records are not bank settlement statements. Do not estimate actual fees by subtracting a guessed percentage.

Errors & retries

Admission denial is an evaluated HTTP 200 response with valid: false. Authentication, authorization and infrastructure errors use HTTP error codes. Use X-Request-Id when investigating failures. Honor Retry-After for 429 responses. The default integration limit is 600 requests per minute.

Pagination & synchronization

List endpoints return data, has_more and next_after. Keep fetching until has_more is false. Change history is retained for 90 days. If a cursor expires (HTTP 410, cursor_expired), capture a new cursor and rebuild your snapshot. Use the synchronization guide below before building a local mirror. Changes are durable invalidations: fetch the referenced resource to obtain its current authorized state. Webhooks may arrive out of order or more than once.

Compatibility

Ignore additional response fields. Existing supported fields keep their types and meanings. Treat unknown denial reasons as denial. Breaking changes require a new supported API contract. Verify integrations in the sandbox before enabling live access.

Mobile apps and broader business operations

A business-owned backend may use scoped credentials. Customer and staff apps need user authorization rather than a shared business secret. Order creation and inventory adjustment use existing Makseb business rules. Customer checkout uses an order placement capability. Never treat a customer identifier as authentication, or place an integration secret in an app. A complete customer or staff account API is not yet part of the v1 API.

Build an iOS app

  1. Your backend stores a separate Makseb integration credential with the minimum branches and scopes.
  2. The app authenticates users to your backend. Your backend authorizes each business, branch, customer and order before calling Makseb.
  3. Fetch catalog and availability, then create orders with product identifiers. Makseb calculates prices; never accept client-supplied paid status or totals.
  4. Keep the returned placement capability private to the purchaser. Open hosted checkout when available; sandbox payment-provider checkout is deliberately unavailable.
  5. Use the signed receipt capability to retrieve one ticket per visitor. A receipt QR and an admission QR serve different purposes.
  6. Use the change feed and signed webhooks to refresh cached resources. Refresh current server state after reconnecting.

Do not issue one shared merchant login to app users. Staff permissions and customer account identity require an explicit application authorization model.

Bootstrap and maintain a mirror

  1. Capture a starting cursor using the sync endpoint.
  2. Read all pages of each authorized resource into your local store.
  3. Read changes after the starting cursor and refetch affected resources. Process deletions as tombstones. Repeated updates must be harmless.
  4. Persist the next cursor only after successfully applying a page. Continue polling even if you also receive webhooks.
  5. Rebuild the affected mirror whenever you change branch or resource permissions.

The snapshot pages are not one database transaction. Applying changes captured during the initial scan closes that gap. Access decisions are historical events; resource reads are current state.

Signed webhooks

Settings → Developers → Webhooks lets owners select an integration, HTTPS endpoint and supported events. Save the signing secret when it is displayed. The endpoint starts pending and receives no business events until verification succeeds.

For a webhook.verification event, return HTTP 200 JSON containing the exact challenge value. Validate the Makseb-Signature header before trusting any event. Its format is t=UNIX_SECONDS,v1=HEX_HMAC_SHA256. The signed bytes are the timestamp, a period, then the unmodified raw request body. Reject timestamps more than five minutes from your server clock and compare signatures in constant time.

Store event identifiers to deduplicate. Acknowledge only after durably accepting the event, then process it asynchronously. Failed delivery retries with increasing delay up to ten attempts. Owners can inspect failures and replay them. Disabling an integration or removing permissions cancels pending deliveries when authorization is rechecked.

Endpoints must use public HTTPS on port 443. Redirects, private addresses and unsafe hostname resolutions are refused. Payloads contain resource identifiers and change hints rather than complete customer records. Fetch additional data through the authorized API.

Supplier, affiliate and future APIs

The current API authorizes business integrations. Supplier, affiliate and other application APIs are not available yet. They can reuse the API versioning, documentation, sandbox, request logging and webhook patterns, with their own resource namespaces, account ownership checks and permissions.

A business API key must never automatically gain supplier or affiliate authority. New capabilities should be opt-in and additive; existing fields, permissions and meanings remain stable. A breaking change requires a new supported contract rather than silently changing an existing integration.

Product and service IDs

Catalog records have permanent internal UUIDs for orders, inventory and app integrations. Read them through the catalog API when needed. Scanners never need product or service IDs: configure the gate once and send only its gate_id, the scanned qr_code and date_time. Makseb checks the purchased ticket and applies its entry rules. Creating a new service does not require reprogramming the scanner.

Use GET /v1/products/{id} or GET /v1/services/{id} with a scoped API key. An ID is a reference, not permission to read the record. Public storefront slugs are customer links and are separate from API identifiers.

Ticket options and age pricing

Read GET /v1/services/{id}. Each ticket option lists included zones and visitor prices. A single-zone option prices that zone; a package can include several zones or every zone. Select one option per visitor so that one QR carries all included access. Do not create a separate line for every zone of the same visitor. Age ranges use inclusive completed years; a null maximum has no upper age limit. Each price has a permanent variant_id.

The website collects adult, child and other visitor quantities together in one booking action. To build the same experience in your app, add a line for each selected price in one order. Set quantity to 1 and use booking.party_size for the number of visitors in that category. The existing pricing and booking engine checks current prices and shared service capacity.

POST /v1/orders
Authorization: Bearer {{apiKey}}
Idempotency-Key: {{requestId}}
Content-Type: application/json

{
  "branch_id": "{{branchId}}",
  "order_type": "booking",
  "items": [
    {
      "product_id": "{{parkServiceId}}",
      "variant_id": "{{adultVariantId}}",
      "quantity": 1,
      "booking": {
        "date": "{{visitDate}}",
        "time": "09:00",
        "party_size": 2,
        "hours": 1,
        "customer_name": "Example visitor",
        "customer_phone": "+12025550101"
      }
    },
    {
      "product_id": "{{parkServiceId}}",
      "variant_id": "{{childVariantId}}",
      "quantity": 1,
      "booking": {
        "date": "{{visitDate}}",
        "time": "09:00",
        "party_size": 3,
        "hours": 1,
        "customer_name": "Example visitor",
        "customer_phone": "+12025550101"
      }
    }
  ]
}

This example uses the one-hour sample service and requests two adult tickets and three child tickets. For other services, follow the returned booking_rules and availability. After payment, the receipt delivery returns five individual QR codes. Do not generate or substitute ticket QR values yourself.

Each ticket records the option and visitor category sold. Later catalog changes do not change those purchased allowances. Cancelling a booking revokes only tickets linked to that booking. Age categories describe purchased visitor tickets; they do not establish the buyer's age or verify concession eligibility.

Test park entry, zones and exit

Open Developers, select Sandbox, and create an integration with the required branches, access permissions and gates. The synthetic sample service includes adult and child prices, a main entrance, a main exit and zone scanners.

Use Test a visitor ticket in the same API integrations tab. Choose a test service and visitor type, verify your identity, and create a test QR. You can copy the QR value or scan the displayed code. This creates a complimentary synthetic ticket, not a sale or payment.

  1. Scan at a zone before the entrance: access is refused with park_entry_required.
  2. Scan at the main entrance: access is granted and visit_state becomes inside.
  3. Scan at the entrance again with a new scan ID: access is refused as duplicate.
  4. Scan included zones repeatedly: unlimited zones remain eligible while inside; finite allowances are consumed.
  5. Scan at the main exit: visit_state becomes exited.
  6. Try a zone again: access is refused. A single-entry ticket also refuses another park entry.

Retries of old approvals cannot reopen access after the visit changes. The visit_sequence identifies that state change. Inspect reason and status, and keep the controller closed for any denial.

Sandbox keys and tickets cannot authorize live gates through the live API. Keep the configured test endpoint, credential and gate identifiers together.

Multiple zones and bundle pricing

Customers can select several zones or a full-access bundle. Each visitor still receives one QR containing all purchased zone permissions. A zone covered by a selected bundle is not charged again. Partially overlapping bundles are refused; choose one bundle and additional zones that it does not include.

For API order creation, send ticket_variant_ids on each visitor-category item, using one visitor price variant per selected option. Put the effective option with the widest zone coverage first (full access first when coverage is equal) and use its variant as variant_id. Prices must have compatible age ranges. Send quantity: 1 and the category count in booking.party_size. Use separate booking items for different visitor categories, not separate items for each zone. Preserve the usual booking pricing fields, including booking.hours when the catalog duration unit is hours.

The server resolves the combined price and snapshots the unique zone entitlements before accepting the order. TicketChoice.option_ids identifies the effective bundle components. Existing paid tickets keep their original permissions and prices.

Storefront domains and the API

Production storefronts use https://store.makseb.io/BUSINESS_SLUG. Development storefronts use https://dev-store.makseb.io/BUSINESS_SLUG. API clients use the stable API origin for their environment: https://api.makseb.io, https://dev-api.makseb.io or https://sandbox-api.makseb.io.

A verified business-owned domain serves the same storefront and checkout through its tenant-scoped website routes. It does not replace the platform API address or change business, zone, ticket or gate identifiers. Keep integration secrets on the business backend and continue calling the API origin after a domain change. Payment callbacks and signed webhooks retain their configured endpoints.

Weekday offers and fixed-price product bundles

Business owners can choose the active weekdays for an offer. Eligibility is evaluated when checkout is placed, using the order branch timezone. A fixed-price bundle requires the configured quantity of every listed product from the same branch and currency. Additional quantities and add-ons keep their normal price.

The best single applicable offer is applied through normal order placement. The final discount is distributed across the eligible items, preserving invoice totals, tax calculation, inventory quantities and existing paid-order snapshots. There is no separate public Offers management endpoint in this API version.

04 / Data models

Shared schemas.

References such as #/components/schemas/Ticket point to these definitions.

CreatedOrder
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "branch_id": {
      "type": "string",
      "format": "uuid"
    },
    "placement_key": {
      "type": "string"
    },
    "booking_outcomes": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/BookingOutcome"
      }
    }
  }
}
OrderCapability
{
  "type": "object",
  "required": [
    "branch_id",
    "placement_key"
  ],
  "properties": {
    "branch_id": {
      "type": "string",
      "format": "uuid"
    },
    "placement_key": {
      "type": "string",
      "minLength": 32,
      "maxLength": 200
    },
    "language": {
      "enum": [
        "en",
        "ar"
      ]
    }
  }
}
CreateOrder
{
  "type": "object",
  "additionalProperties": false,
  "required": [
    "branch_id",
    "items"
  ],
  "properties": {
    "branch_id": {
      "type": "string",
      "format": "uuid"
    },
    "order_type": {
      "enum": [
        "takeaway",
        "dine_in",
        "booking"
      ]
    },
    "table_number": {
      "type": "integer"
    },
    "customer_phone": {
      "type": "string"
    },
    "note": {
      "type": "string"
    },
    "items": {
      "type": "array",
      "minItems": 1,
      "maxItems": 100,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "product_id",
          "quantity"
        ],
        "properties": {
          "product_id": {
            "type": "string",
            "format": "uuid"
          },
          "variant_id": {
            "type": "string",
            "format": "uuid"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1000,
            "description": "Product units. For a booking line this must be 1; use booking.party_size for visitors or guests."
          },
          "booking": {
            "type": "object",
            "description": "Required for services. Calendar values use the branch time zone. Review booking_outcomes before payment: unavailable lines can be refused.",
            "required": [
              "date",
              "customer_name",
              "customer_phone"
            ],
            "properties": {
              "date": {
                "type": "string",
                "format": "date"
              },
              "time": {
                "type": "string"
              },
              "party_size": {
                "type": "integer",
                "minimum": 1
              },
              "days": {
                "type": "integer",
                "minimum": 1
              },
              "hours": {
                "type": "integer",
                "minimum": 1,
                "description": "Required for hour-based services. Use booking_rules.duration_value for the standard duration, or another duration allowed by the service."
              },
              "resource_id": {
                "type": "string",
                "format": "uuid"
              },
              "customer_name": {
                "type": "string"
              },
              "customer_phone": {
                "type": "string"
              }
            }
          },
          "ticket_variant_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            },
            "minItems": 1,
            "maxItems": 30,
            "uniqueItems": true,
            "description": "Optional combined ticket selection for one visitor category. Use one price variant per option. Fully covered standalone zones add no charge; partially overlapping bundles are refused. Set variant_id to the first effective option, with the widest zone coverage first and full-access options first when coverage is equal. A booking line produces one ticket per visitor with the union of zones."
          }
        },
        "allOf": [
          {
            "if": {
              "required": [
                "booking"
              ]
            },
            "then": {
              "properties": {
                "quantity": {
                  "const": 1
                }
              }
            }
          }
        ]
      }
    }
  }
}
Error
{
  "type": "object",
  "required": [
    "error"
  ],
  "properties": {
    "error": {
      "type": "object",
      "required": [
        "code",
        "request_id"
      ],
      "properties": {
        "code": {
          "type": "string"
        },
        "request_id": {
          "type": "string",
          "format": "uuid"
        }
      }
    }
  }
}
Page
{
  "type": "object",
  "required": [
    "data",
    "has_more",
    "next_after"
  ],
  "properties": {
    "data": {
      "type": "array",
      "items": {}
    },
    "has_more": {
      "type": "boolean"
    },
    "next_after": {
      "type": [
        "string",
        "null"
      ],
      "format": "uuid"
    }
  }
}
Branch
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string"
    },
    "currency_code": {
      "type": "string"
    },
    "timezone": {
      "type": "string"
    }
  }
}
CatalogItem
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "branch_id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": [
        "string",
        "null"
      ]
    },
    "category": {
      "type": "string"
    },
    "item_type": {
      "enum": [
        "product",
        "service"
      ]
    },
    "unit_price_minor": {
      "type": [
        "integer",
        "null"
      ]
    },
    "currency_code": {
      "type": "string"
    },
    "image_url": {
      "type": [
        "string",
        "null"
      ]
    },
    "store_published": {
      "type": "boolean"
    },
    "variants": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string"
          },
          "unit_price_minor": {
            "type": [
              "integer",
              "null"
            ]
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      }
    },
    "booking_rules": {
      "type": "object",
      "properties": {
        "booking_type": {
          "type": [
            "string",
            "null"
          ]
        },
        "pricing_basis": {
          "type": [
            "string",
            "null"
          ]
        },
        "duration_value": {
          "type": [
            "integer",
            "null"
          ]
        },
        "duration_unit": {
          "type": [
            "string",
            "null"
          ]
        },
        "capacity": {
          "type": [
            "integer",
            "null"
          ]
        },
        "requires_resource": {
          "type": [
            "boolean",
            "null"
          ]
        }
      }
    },
    "ticket_access": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "zone_id": {
            "type": "string",
            "format": "uuid"
          },
          "zone_name": {
            "type": "string"
          },
          "entry_limit": {
            "type": "integer"
          },
          "description": {
            "type": "string"
          },
          "image_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "unlimited_inside": {
            "type": "boolean"
          },
          "capacity": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "description": "Maximum simultaneous visitors shared by all products using this zone. Null means no configured limit."
          }
        }
      },
      "description": "Service areas and default allowances. If ticket_options exist, the selected option determines which areas the purchased visitor ticket includes. Zone UUIDs survive renaming and photo changes."
    },
    "ticket_rules": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "park_entry_required": {
          "type": "boolean"
        },
        "park_entry_limit": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 1
        },
        "validity_mode": {
          "type": "string",
          "description": "calendar_date for zoo and theme park visits; scheduled for other services."
        }
      },
      "description": "With entry tracking enabled, zone access requires an active visit. A limit of 1 blocks park re-entry after exit; null permits re-entry while the ticket is valid."
    },
    "ticket_options": {
      "type": [
        "array",
        "null"
      ],
      "items": {
        "$ref": "#/components/schemas/TicketOption"
      }
    }
  }
}
InventoryItem
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "branch_id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string"
    },
    "unit": {
      "type": "string"
    },
    "stock": {
      "type": "number",
      "description": "Quantity of the unvaried item, not an aggregate of variant quantities."
    },
    "threshold": {
      "type": "number"
    },
    "variants": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "stock": {
            "type": "number"
          },
          "threshold": {
            "type": "number"
          }
        }
      }
    }
  }
}
Order
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "branch_id": {
      "type": "string",
      "format": "uuid"
    },
    "status": {
      "type": "string"
    },
    "payment_status": {
      "type": "string"
    },
    "refund_status": {
      "type": "string"
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time"
    },
    "currency_code": {
      "type": "string"
    },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "quantity": {
            "type": "number"
          },
          "unit_price_minor": {
            "type": "integer"
          }
        }
      }
    }
  }
}
Booking
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "branch_id": {
      "type": "string",
      "format": "uuid"
    },
    "menu_item_id": {
      "type": "string",
      "format": "uuid"
    },
    "order_id": {
      "type": [
        "string",
        "null"
      ],
      "format": "uuid"
    },
    "booking_date": {
      "type": "string",
      "format": "date"
    },
    "booking_time": {
      "type": [
        "string",
        "null"
      ]
    },
    "booking_end_at": {
      "type": "string",
      "format": "date-time"
    },
    "status": {
      "type": "string"
    },
    "party_size": {
      "type": "integer"
    }
  }
}
Customer
{
  "type": "object",
  "description": "Minimal projection. Contact details and business-wide metrics are not granted by this scope.",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": [
        "string",
        "null"
      ]
    },
    "first_seen_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
Payment
{
  "type": "object",
  "description": "Amounts are recorded facts, not estimates. Null fees are unknown, not zero. This object is not a bank settlement statement.",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "order_id": {
      "type": "string",
      "format": "uuid"
    },
    "branch_id": {
      "type": "string",
      "format": "uuid"
    },
    "amount_minor": {
      "type": "integer"
    },
    "currency_code": {
      "type": "string"
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "gateway_transaction_id": {
      "type": [
        "string",
        "null"
      ]
    },
    "gateway_fee_status": {
      "type": "string"
    },
    "gateway_fee_minor": {
      "type": [
        "integer",
        "null"
      ]
    },
    "gateway_fee_vat_minor": {
      "type": [
        "integer",
        "null"
      ]
    },
    "gateway_fee_vat_status": {
      "type": "string"
    },
    "currency_source": {
      "type": "string",
      "enum": [
        "order_snapshot",
        "legacy_branch"
      ],
      "description": "legacy_branch means the original currency was not recorded; the current branch currency is shown as an inference."
    }
  }
}
Ticket
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "branch_id": {
      "type": "string",
      "format": "uuid"
    },
    "status": {
      "enum": [
        "active",
        "revoked",
        "cancelled"
      ]
    },
    "valid_from": {
      "type": "string",
      "format": "date-time"
    },
    "valid_until": {
      "type": "string",
      "format": "date-time"
    },
    "policy_revision": {
      "type": "integer"
    },
    "entitlements": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "zone_id": {
            "type": "string",
            "format": "uuid"
          },
          "entry_limit": {
            "type": "integer"
          },
          "remaining_entries": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Null for unlimited zone access. Finite allowances are consumed only on zone entry."
          },
          "unlimited_inside": {
            "type": "boolean"
          }
        }
      }
    },
    "ticket_choice": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/TicketChoice"
        },
        {
          "type": "null"
        }
      ]
    },
    "visit_state": {
      "type": "string",
      "enum": [
        "outside",
        "inside",
        "exited"
      ]
    },
    "visit_sequence": {
      "type": "integer"
    },
    "park_entry_required": {
      "type": "boolean"
    },
    "park_entry_limit": {
      "type": [
        "integer",
        "null"
      ]
    },
    "park_entries_used": {
      "type": "integer"
    }
  }
}
Scan
{
  "type": "object",
  "properties": {
    "qr_code": {
      "type": "string",
      "minLength": 16,
      "maxLength": 512,
      "description": "The complete opaque QR payload; do not log it."
    },
    "gate_id": {
      "type": "string",
      "description": "Registered gate UUID or its external identifier."
    },
    "date_time": {
      "type": "string",
      "format": "date-time",
      "description": "Device time with an explicit offset; eligibility uses server time."
    }
  }
}
AccessDecision
{
  "type": "object",
  "required": [
    "valid",
    "ticket_id",
    "status",
    "reason",
    "access_attempt_id"
  ],
  "properties": {
    "valid": {
      "type": "boolean"
    },
    "ticket_id": {
      "type": [
        "string",
        "null"
      ],
      "format": "uuid"
    },
    "status": {
      "enum": [
        "access_granted",
        "access_failed",
        "duplicate"
      ]
    },
    "reason": {
      "type": [
        "string",
        "null"
      ],
      "description": "Includes park_entry_required, already_inside_park, park_entries_exhausted, park_not_included, not_inside_park, visit_changed, zone_not_included, entries_exhausted and expiry/revocation reasons. Treat unknown denial reasons as denied."
    },
    "access_attempt_id": {
      "type": "string",
      "format": "uuid"
    },
    "zone_id": {
      "type": "string",
      "format": "uuid"
    },
    "remaining_entries": {
      "type": [
        "integer",
        "null"
      ]
    },
    "actuation_expires_at": {
      "type": "string",
      "format": "date-time"
    },
    "visit_state": {
      "type": [
        "string",
        "null"
      ],
      "description": "Presence based on accepted entrance/exit scans, not GPS."
    },
    "ticket_choice": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/TicketChoice"
        },
        {
          "type": "null"
        }
      ]
    },
    "visit_sequence": {
      "type": [
        "integer",
        "null"
      ]
    },
    "access_kind": {
      "type": "string",
      "enum": [
        "park",
        "zone"
      ]
    },
    "direction": {
      "type": "string",
      "enum": [
        "entry",
        "exit"
      ]
    },
    "unlimited_inside": {
      "type": "boolean"
    },
    "zone_capacity": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 0,
      "description": "Configured maximum people inside; null means unlimited."
    },
    "zone_available": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 0,
      "description": "Available places at decision time; null means unlimited."
    },
    "zone_occupied": {
      "type": "integer",
      "minimum": 0,
      "description": "Recorded entries that have not exited. Includes approved entry scans."
    },
    "inside_zone": {
      "type": "boolean",
      "description": "Whether this visitor is recorded inside the scanned zone."
    },
    "zone_sequence": {
      "type": "integer",
      "minimum": 0,
      "description": "Presence generation. Old approvals cannot reopen after a later entry or exit."
    }
  }
}
Validation
{
  "type": "object",
  "required": [
    "valid",
    "ticket_id",
    "status",
    "gate_eligible",
    "consumed"
  ],
  "properties": {
    "valid": {
      "type": "boolean"
    },
    "ticket_id": {
      "type": [
        "string",
        "null"
      ],
      "format": "uuid"
    },
    "status": {
      "enum": [
        "active",
        "access_granted",
        "access_failed",
        "duplicate"
      ]
    },
    "reason": {
      "type": [
        "string",
        "null"
      ]
    },
    "gate_eligible": {
      "type": [
        "boolean",
        "null"
      ]
    },
    "consumed": {
      "const": false,
      "description": "Always false: a validation request does not consume an entry."
    },
    "valid_until": {
      "type": "string",
      "format": "date-time"
    },
    "visit_state": {
      "type": [
        "string",
        "null"
      ],
      "description": "Presence based on accepted entrance/exit scans, not GPS."
    },
    "ticket_choice": {
      "anyOf": [
        {
          "$ref": "#/components/schemas/TicketChoice"
        },
        {
          "type": "null"
        }
      ]
    },
    "park_entry_required": {
      "type": "boolean"
    },
    "park_entries_remaining": {
      "type": [
        "integer",
        "null"
      ]
    },
    "ticket_consumed": {
      "type": "boolean",
      "description": "Whether a simple visitor ticket has exhausted its finite entry allowance. This is ticket state; consumed remains false because validation does not use an entry."
    },
    "zone_capacity": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 0,
      "description": "Configured maximum people inside; null means unlimited."
    },
    "zone_available": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 0,
      "description": "Available places at decision time; null means unlimited."
    },
    "zone_occupied": {
      "type": "integer",
      "minimum": 0,
      "description": "Recorded entries that have not exited. Includes approved entry scans."
    },
    "inside_zone": {
      "type": "boolean",
      "description": "Whether this visitor is recorded inside the scanned zone."
    },
    "zone_sequence": {
      "type": "integer",
      "minimum": 0,
      "description": "Presence generation. Old approvals cannot reopen after a later entry or exit."
    }
  }
}
Event
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "sequence": {
      "type": "integer"
    },
    "event_type": {
      "type": "string"
    },
    "resource_id": {
      "type": "string",
      "format": "uuid"
    },
    "resource_type": {
      "type": "string"
    },
    "branch_id": {
      "type": [
        "string",
        "null"
      ],
      "format": "uuid"
    },
    "payload_version": {
      "const": "v1"
    },
    "data": {
      "type": "object"
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
BookingOutcome
{
  "type": "object",
  "properties": {
    "item_index": {
      "type": "integer",
      "minimum": 0
    },
    "status": {
      "enum": [
        "booked",
        "refused"
      ]
    },
    "booking_id": {
      "type": [
        "string",
        "null"
      ],
      "format": "uuid"
    },
    "reason": {
      "type": [
        "string",
        "null"
      ]
    }
  }
}
Refund
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "order_id": {
      "type": "string",
      "format": "uuid"
    },
    "branch_id": {
      "type": "string",
      "format": "uuid"
    },
    "amount_minor": {
      "type": "integer"
    },
    "recorded_fee_minor": {
      "type": [
        "integer",
        "null"
      ],
      "description": "Recorded refund fee; not evidence of bank settlement."
    },
    "currency_code": {
      "type": "string"
    },
    "currency_source": {
      "type": "string",
      "enum": [
        "order_snapshot",
        "legacy_branch"
      ]
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
TicketPrice
{
  "type": "object",
  "required": [
    "id",
    "variant_id",
    "name",
    "min_age",
    "max_age",
    "price_minor",
    "currency_code"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "variant_id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string"
    },
    "min_age": {
      "type": "integer",
      "minimum": 0,
      "maximum": 150
    },
    "max_age": {
      "type": [
        "integer",
        "null"
      ],
      "minimum": 0,
      "maximum": 150
    },
    "price_minor": {
      "type": "integer",
      "minimum": 0
    },
    "currency_code": {
      "type": "string"
    }
  },
  "description": "A visitor age category. Use variant_id when ordering. Ages are inclusive completed years; null max_age means no upper age limit. Prices are per visitor in minor units."
}
TicketOption
{
  "type": "object",
  "required": [
    "id",
    "name",
    "all_zones",
    "zone_ids",
    "prices"
  ],
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid"
    },
    "name": {
      "type": "string"
    },
    "all_zones": {
      "type": "boolean"
    },
    "zone_ids": {
      "type": "array",
      "items": {
        "type": "string",
        "format": "uuid"
      }
    },
    "prices": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/TicketPrice"
      }
    }
  },
  "description": "A ticket package with its own included zones and visitor prices. all_zones includes the areas configured for this service at purchase time."
}
TicketChoice
{
  "type": "object",
  "properties": {
    "option_id": {
      "type": "string",
      "format": "uuid"
    },
    "option_name": {
      "type": "string"
    },
    "price_id": {
      "type": "string",
      "format": "uuid"
    },
    "variant_id": {
      "type": "string",
      "format": "uuid"
    },
    "visitor_type": {
      "type": "string"
    },
    "min_age": {
      "type": "integer"
    },
    "max_age": {
      "type": [
        "integer",
        "null"
      ]
    },
    "option_ids": {
      "type": "array",
      "items": {
        "type": "string",
        "format": "uuid"
      },
      "description": "All effective ticket options in a combined purchase. option_id remains the primary option for older clients."
    }
  },
  "description": "The immutable option and visitor category recorded for this ticket when sold."
}