{
  "openapi": "3.0.3",
  "info": {
    "title": "TMS Gateway API",
    "version": "1.0.0",
    "description": "API for registering operators and managing their TMS credentials. Once configured, operators and their venues become available for booking operations via the Bookings API.\n\nThis API provides endpoints to:\n- Register, retrieve, update, and deregister operators\n- Manage TMS credentials for each operator\n\n**Supported TMS Systems:**\n- **Collins (CO)** - BearerToken authentication\n- **SevenRooms (SR)** - ClientCredentials authentication\n- **Zonal (ZO)** - BaseAuth authentication\n\n**Authentication Fields by TMS Type:**\n\n| TMS | Auth Type | Required Fields |\n|-----|-----------|-----------------|\n| Collins (CO) | BearerToken | `bearer`, `externalOperatorId` |\n| SevenRooms (SR) | ClientCredentials | `clientId`, `secretId` |\n| Zonal (ZO) | BaseAuth | `clientId`, `secretId` |\n"
  },
  "servers": [
    {
      "url": "https://api.bookabletech.com",
      "description": "Live"
    }
  ],
  "tags": [
    {
      "name": "operators",
      "description": "Operators are the hospitality businesses (e.g. Stonegate, Nightcap, Big Table Group) whose venues you want to make bookable through your integration. Registering an operator is the first step before connecting any TMS credentials.\n"
    },
    {
      "name": "operator-tms-credentials",
      "description": "Credentials connect a registered operator to their TMS. Each credential set tells Bookable how to authenticate with a specific TMS on the operator's behalf — unlocking real-time availability and booking capability for that operator's venues.\nAn operator may hold credentials for multiple TMS systems (e.g. Collins for some venues, SevenRooms for others).\n"
    }
  ],
  "paths": {
    "/operators": {
      "get": {
        "tags": [
          "operators"
        ],
        "summary": "List all operators",
        "description": "Retrieve a list of all operators in the system.",
        "operationId": "listOperators",
        "responses": {
          "200": {
            "description": "List of operators successfully retrieved",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperatorList"
                },
                "example": [
                  {
                    "id": 1,
                    "businessName": "Acme Restaurant Group",
                    "createdAt": "2025-01-10T08:00:00Z",
                    "updatedAt": "2025-02-15T10:30:00Z"
                  },
                  {
                    "id": 2,
                    "businessName": "Downtown Dining Co.",
                    "createdAt": "2025-01-12T09:30:00Z",
                    "updatedAt": "2025-01-12T09:30:00Z"
                  }
                ]
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        },
        "security": [
          {
            "Live": [
              "venue-group:read"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "operators"
        ],
        "summary": "Create a new operator",
        "description": "Create a new operator with the provided details.",
        "operationId": "createOperator",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OperatorRequest"
              },
              "example": {
                "businessName": "New Restaurant Group",
                "partnerSource": "Partner Trading Name"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Operator successfully created",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Operator"
                },
                "example": {
                  "id": 3,
                  "businessName": "New Restaurant Group",
                  "createdAt": "2025-02-20T14:00:00Z",
                  "updatedAt": "2025-02-20T14:00:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        },
        "security": [
          {
            "Live": [
              "venue-group:create"
            ]
          }
        ]
      }
    },
    "/operators/{operatorId}": {
      "get": {
        "tags": [
          "operators"
        ],
        "summary": "Get a specific operator",
        "description": "Retrieve the details of a specific operator by its ID.",
        "operationId": "getOperator",
        "parameters": [
          {
            "name": "operatorId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the operator",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Operator successfully retrieved",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Operator"
                },
                "example": {
                  "id": 1,
                  "businessName": "Acme Restaurant Group",
                  "createdAt": "2025-01-10T08:00:00Z",
                  "updatedAt": "2025-02-15T10:30:00Z"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        },
        "security": [
          {
            "Live": [
              "venue-group:read"
            ]
          }
        ]
      },
      "put": {
        "tags": [
          "operators"
        ],
        "summary": "Update an operator",
        "description": "Update the details of an existing operator.",
        "operationId": "updateOperator",
        "parameters": [
          {
            "name": "operatorId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the operator",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OperatorUpdateRequest"
              },
              "example": {
                "businessName": "Updated Restaurant Group Name"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Operator successfully updated",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Operator"
                },
                "example": {
                  "id": 1,
                  "businessName": "Updated Restaurant Group Name",
                  "createdAt": "2025-01-10T08:00:00Z",
                  "updatedAt": "2025-02-20T15:45:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        },
        "security": [
          {
            "Live": [
              "venue-group:update"
            ]
          }
        ]
      },
      "delete": {
        "tags": [
          "operators"
        ],
        "summary": "Delete an operator",
        "description": "Remove an operator from the system.",
        "operationId": "deleteOperator",
        "parameters": [
          {
            "name": "operatorId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the operator",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Operator successfully deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalServerError"
          }
        },
        "security": [
          {
            "Live": [
              "venue-group:delete"
            ]
          }
        ]
      }
    },
    "/operators/{operatorId}/tms-credentials": {
      "get": {
        "tags": [
          "operator-tms-credentials"
        ],
        "summary": "List TMS credentials for an operator",
        "description": "Retrieve all TMS credentials associated with a specific operator.",
        "operationId": "listOperatorTmsCredentials",
        "parameters": [
          {
            "name": "operatorId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the operator",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of TMS credentials successfully retrieved",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperatorTmsCredentialsList"
                },
                "example": [
                  {
                    "operatorId": 1,
                    "tmsId": 1,
                    "tmsName": "Collins",
                    "tmsSlug": "CO",
                    "active": true,
                    "createdAt": "2025-01-15T10:30:00Z",
                    "updatedAt": "2025-02-10T14:20:00Z"
                  },
                  {
                    "operatorId": 1,
                    "tmsId": 2,
                    "tmsName": "SevenRooms",
                    "tmsSlug": "SR",
                    "active": true,
                    "createdAt": "2025-01-20T09:15:00Z",
                    "updatedAt": "2025-01-20T09:15:00Z"
                  }
                ]
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "security": [
          {
            "Live": [
              "venue-group:read"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "operator-tms-credentials"
        ],
        "summary": "Create TMS credentials for an operator",
        "description": "Create a new TMS credentials to link a table management system to an operator with the necessary credentials.",
        "operationId": "createOperatorTmsCredentials",
        "parameters": [
          {
            "name": "operatorId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the operator",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OperatorTmsCredentialsRequest"
              },
              "example": {
                "tmsSlug": "CO",
                "clientId": "44966392-f2d4-4929-8c9a-e87a0e7dc856",
                "secretId": "LjjXs5$3M%Btx@tt",
                "bearer": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
                "externalOperatorId": "514ada610df690b6770000fd",
                "active": true
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "TMS credentials successfully created",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperatorTmsCredentials"
                },
                "example": {
                  "operatorId": 1,
                  "tmsId": 1,
                  "tmsName": "Collins",
                  "tmsSlug": "CO",
                  "clientId": null,
                  "secretId": null,
                  "bearer": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
                  "externalOperatorId": "514ada610df690b6770000fd",
                  "active": true,
                  "createdAt": "2025-02-19T10:30:00Z",
                  "updatedAt": "2025-02-19T10:30:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "security": [
          {
            "Live": [
              "venue-group:update"
            ]
          }
        ]
      }
    },
    "/operators/{operatorId}/tms-credentials/{tmsId}": {
      "get": {
        "tags": [
          "operator-tms-credentials"
        ],
        "summary": "Get a specific TMS credentials",
        "description": "Retrieve the details of a specific TMS credentials for an operator, including credentials and settings.",
        "operationId": "getOperatorTmsCredentials",
        "parameters": [
          {
            "name": "operatorId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the operator",
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "tmsId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the TMS",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "TMS credentials successfully retrieved",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperatorTmsCredentials"
                },
                "example": {
                  "operatorId": 1,
                  "tmsId": 1,
                  "tmsName": "Collins",
                  "tmsSlug": "CO",
                  "clientId": null,
                  "secretId": null,
                  "bearer": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
                  "externalOperatorId": "514ada610df690b6770000fd",
                  "active": true,
                  "createdAt": "2025-01-15T10:30:00Z",
                  "updatedAt": "2025-02-10T14:20:00Z"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "security": [
          {
            "Live": [
              "venue-group:update"
            ]
          }
        ]
      },
      "put": {
        "tags": [
          "operator-tms-credentials"
        ],
        "summary": "Update TMS credentials",
        "description": "Update the credentials and settings of an existing TMS credentials for an operator.",
        "operationId": "updateOperatorTmsCredentials",
        "parameters": [
          {
            "name": "operatorId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the operator",
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "tmsId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the TMS",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OperatorTmsCredentialsUpdateRequest"
              },
              "example": {
                "clientId": "44966392-f2d4-4929-8c9a-e87a0e7dc856",
                "secretId": "LjjXs5$3M%Btx@tt",
                "bearer": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
                "externalOperatorId": "514ada610df690b6770000fd",
                "active": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "TMS credentials successfully updated",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OperatorTmsCredentials"
                },
                "example": {
                  "operatorId": 1,
                  "tmsId": 1,
                  "tmsName": "Collins",
                  "tmsSlug": "CO",
                  "clientId": null,
                  "secretId": null,
                  "bearer": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
                  "externalOperatorId": "514ada610df690b6770000fd",
                  "active": true,
                  "createdAt": "2025-01-15T10:30:00Z",
                  "updatedAt": "2025-02-19T16:45:00Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "security": [
          {
            "Live": [
              "venue-group:update"
            ]
          }
        ]
      },
      "delete": {
        "tags": [
          "operator-tms-credentials"
        ],
        "summary": "Delete TMS credentials",
        "description": "Remove a TMS credentials from an operator.",
        "operationId": "deleteOperatorTmsCredentials",
        "parameters": [
          {
            "name": "operatorId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the operator",
            "schema": {
              "type": "integer",
              "example": 1
            }
          },
          {
            "name": "tmsId",
            "in": "path",
            "required": true,
            "description": "The unique identifier of the TMS",
            "schema": {
              "type": "integer",
              "example": 1
            }
          }
        ],
        "responses": {
          "204": {
            "description": "TMS credentials successfully deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          }
        },
        "security": [
          {
            "Live": [
              "venue-group:update"
            ]
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "Operator": {
        "type": "object",
        "description": "Complete operator details",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The unique identifier of the operator",
            "example": 1
          },
          "businessName": {
            "type": "string",
            "description": "Business name of the operator",
            "example": "Acme Restaurant Group"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the operator was created",
            "example": "2025-01-10T08:00:00Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the operator was last updated",
            "example": "2025-02-15T10:30:00Z"
          }
        },
        "required": [
          "id",
          "businessName",
          "createdAt",
          "updatedAt"
        ]
      },
      "OperatorList": {
        "type": "array",
        "description": "List of operators",
        "items": {
          "$ref": "#/components/schemas/Operator"
        }
      },
      "OperatorRequest": {
        "type": "object",
        "description": "Request payload for creating a new operator",
        "properties": {
          "businessName": {
            "type": "string",
            "description": "Business name of the operator",
            "minLength": 1,
            "maxLength": 255,
            "example": "New Restaurant Group"
          },
          "partnerSource": {
            "type": "string",
            "nullable": true,
            "description": "Partner source identifier.\nThis is required for partner users.\nThis will be used to track bookings that come from your integration with this operator.\nIf you have been working with the operator already, it is likely they already have created a label for your channel. Please ask for this to continue to use the same partnerSource.\n",
            "minLength": 1,
            "maxLength": 255,
            "example": "Partner Trading Name"
          }
        },
        "required": [
          "businessName"
        ]
      },
      "OperatorUpdateRequest": {
        "type": "object",
        "description": "Request payload for updating an existing operator",
        "properties": {
          "businessName": {
            "type": "string",
            "description": "Updated business name of the operator",
            "minLength": 1,
            "maxLength": 255,
            "example": "Updated Restaurant Group Name"
          }
        },
        "required": [
          "businessName"
        ]
      },
      "OperatorTmsCredentialsList": {
        "type": "array",
        "description": "List of TMS credentials for an operator",
        "items": {
          "$ref": "#/components/schemas/OperatorTmsCredentialsSummary"
        }
      },
      "OperatorTmsCredentialsSummary": {
        "type": "object",
        "description": "Summary of a TMS credentials (without sensitive credentials)",
        "properties": {
          "operatorId": {
            "type": "integer",
            "description": "The unique identifier of the operator",
            "example": 1
          },
          "tmsId": {
            "type": "integer",
            "description": "The unique identifier of the TMS",
            "example": 1
          },
          "tmsName": {
            "type": "string",
            "description": "The name of the TMS",
            "example": "Collins"
          },
          "tmsSlug": {
            "type": "string",
            "description": "The slug identifier of the TMS",
            "example": "CO"
          },
          "active": {
            "type": "boolean",
            "description": "Whether this TMS credentials is currently active",
            "example": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the connection was created",
            "example": "2025-01-15T10:30:00Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the connection was last updated",
            "example": "2025-02-10T14:20:00Z"
          }
        },
        "required": [
          "operatorId",
          "tmsId",
          "tmsName",
          "tmsSlug",
          "active"
        ]
      },
      "OperatorTmsCredentials": {
        "type": "object",
        "description": "Complete TMS credentials for an operator including credentials",
        "properties": {
          "operatorId": {
            "type": "integer",
            "description": "The unique identifier of the operator",
            "example": 1
          },
          "tmsId": {
            "type": "integer",
            "description": "The unique identifier of the TMS",
            "example": 1
          },
          "tmsName": {
            "type": "string",
            "description": "The name of the TMS",
            "example": "Collins"
          },
          "tmsSlug": {
            "type": "string",
            "description": "The slug identifier of the TMS",
            "example": "CO"
          },
          "clientId": {
            "type": "string",
            "nullable": true,
            "description": "Client ID used for authentication with the TMS. Required for BaseAuth and ClientCredentials auth types.",
            "example": "44966392-f2d4-4929-8c9a-e87a0e7dc856"
          },
          "secretId": {
            "type": "string",
            "nullable": true,
            "description": "Client secret used for authentication with the TMS. Required for BaseAuth and ClientCredentials auth types.",
            "example": "LjjXs5$3M%Btx@tt"
          },
          "bearer": {
            "type": "string",
            "nullable": true,
            "description": "Bearer token used for authentication with the TMS. Required for BearerToken auth type (e.g., Collins).",
            "example": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
          },
          "externalOperatorId": {
            "type": "string",
            "description": "External identifier for the operator in the TMS system. Format varies by TMS (hex string for Collins, UUID for others, or empty string).",
            "example": "514ada610df690b6770000fd"
          },
          "active": {
            "type": "boolean",
            "description": "Whether this TMS credentials is currently active",
            "example": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the connection was created",
            "example": "2025-01-15T10:30:00Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the connection was last updated",
            "example": "2025-02-10T14:20:00Z"
          },
          "message": {
            "type": "string",
            "nullable": true,
            "description": "extra notes",
            "example": "sync will start at 6am the next day as per Zonal rules"
          }
        },
        "required": [
          "operatorId",
          "tmsId",
          "tmsName",
          "tmsSlug",
          "externalOperatorId",
          "active"
        ]
      },
      "OperatorTmsCredentialsRequest": {
        "type": "object",
        "description": "Request payload for creating a new TMS credentials",
        "properties": {
          "tmsSlug": {
            "type": "string",
            "description": "The slug identifier of the TMS to connect. Supported values:\n- `CO` - Collins (uses BearerToken authentication)\n- `SR` - SevenRooms (uses ClientCredentials authentication)\n- `ZO` - Zonal (uses BaseAuth authentication)\n",
            "enum": [
              "CO",
              "SR",
              "ZO"
            ],
            "example": "CO"
          },
          "clientId": {
            "type": "string",
            "nullable": true,
            "description": "Client ID for authentication. Required for BaseAuth and ClientCredentials TMS types.",
            "example": "44966392-f2d4-4929-8c9a-e87a0e7dc856"
          },
          "secretId": {
            "type": "string",
            "nullable": true,
            "description": "Client secret for authentication. Required for BaseAuth and ClientCredentials TMS types.",
            "example": "LjjXs5$3M%Btx@tt"
          },
          "bearer": {
            "type": "string",
            "nullable": true,
            "description": "Bearer token for authentication. Required for BearerToken TMS type (e.g., Collins).",
            "example": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
          },
          "externalOperatorId": {
            "type": "string",
            "description": "External identifier for the operator in the TMS system",
            "example": "514ada610df690b6770000fd"
          },
          "active": {
            "type": "boolean",
            "description": "Whether this TMS credentials should be active",
            "example": true
          }
        },
        "required": [
          "tmsSlug",
          "externalOperatorId",
          "active"
        ]
      },
      "OperatorTmsCredentialsUpdateRequest": {
        "type": "object",
        "description": "Request payload for updating an existing TMS credentials (tmsId is in the URL path)",
        "properties": {
          "clientId": {
            "type": "string",
            "nullable": true,
            "description": "Client ID for authentication. Required for BaseAuth and ClientCredentials TMS types.",
            "example": "44966392-f2d4-4929-8c9a-e87a0e7dc856"
          },
          "secretId": {
            "type": "string",
            "nullable": true,
            "description": "Client secret for authentication. Required for BaseAuth and ClientCredentials TMS types.",
            "example": "LjjXs5$3M%Btx@tt"
          },
          "bearer": {
            "type": "string",
            "nullable": true,
            "description": "Bearer token for authentication. Required for BearerToken TMS type (e.g., Collins).",
            "example": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9..."
          },
          "externalOperatorId": {
            "type": "string",
            "description": "External identifier for the operator in the TMS system",
            "example": "514ada610df690b6770000fd"
          },
          "active": {
            "type": "boolean",
            "description": "Whether this TMS credentials should be active",
            "example": true
          }
        },
        "required": [
          "externalOperatorId",
          "active"
        ]
      },
      "ClientError": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "A URI reference [rfc9457] that identifies the problem type. This specification encourages that, when dereferenced, it provides human-readable documentation for the problem type (e.g., using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be \"about:blank\"."
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization."
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "description": "The HTTP status code [rfc9457, Section 3.1.12] generated by the origin server for this occurrence of the problem."
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence of the problem."
          },
          "code": {
            "type": "string",
            "description": "Error code in the format RESOURCE-X-NNN where X is R (retryable) or N (non-retryable). See ErrorCatalog.md for all error codes.",
            "example": "VALID-N-001"
          },
          "isRetryable": {
            "type": "boolean",
            "description": "Indicates whether the error is retryable. If true, the request may succeed if retried. If false, the request will fail again with the same input."
          },
          "traceId": {
            "type": "string",
            "description": "Request trace identifier for debugging and correlation purposes.",
            "example": "0HNJ2BG2TU3BU:00000001"
          },
          "errors": {
            "type": "object",
            "nullable": true,
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Validation errors dictionary mapping field names to arrays of error messages. Only present for validation errors (VALID-N-001).",
            "example": {
              "Date": [
                "Availability date cannot be in the past."
              ],
              "EndTime": [
                "EndTime must be after StartTime."
              ]
            }
          }
        },
        "required": [
          "title",
          "status",
          "code",
          "isRetryable"
        ]
      },
      "ServerError": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "A URI reference [rfc9457] that identifies the problem type. This specification encourages that, when dereferenced, it provides human-readable documentation for the problem type (e.g., using HTML [W3C.REC-html5-20141028]). When this member is not present, its value is assumed to be \"about:blank\"."
          },
          "title": {
            "type": "string",
            "description": "A short, human-readable summary of the problem type. It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization."
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "description": "The HTTP status code [rfc9457, Section 3.1.12] generated by the origin server for this occurrence of the problem."
          },
          "detail": {
            "type": "string",
            "description": "A human-readable explanation specific to this occurrence of the problem."
          },
          "code": {
            "type": "string",
            "description": "Error code in the format RESOURCE-X-NNN where X is R (retryable) or N (non-retryable). See ErrorCatalog.md for all error codes.",
            "example": "BOOK-N-001"
          },
          "isRetryable": {
            "type": "boolean",
            "description": "Indicates whether the error is retryable. If true, the request may succeed if retried. If false, the request will fail again with the same input."
          },
          "traceId": {
            "type": "string",
            "description": "Request trace identifier for debugging and correlation purposes.",
            "example": "0HNJ2BG2TU3BU:00000001"
          }
        },
        "required": [
          "title",
          "status",
          "code",
          "isRetryable"
        ]
      }
    },
    "securitySchemes": {
      "Live": {
        "type": "oauth2",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://auth.bookabletech.com/oauth/token",
            "scopes": {
              "venue-group:read": "Grants read access to venue group details and RMS configurations",
              "venue-group:create": "Grants permission to create venue group RMS configurations",
              "venue-group:update": "Grants permission to update venue group RMS configurations",
              "venue-group:delete": "Grants permission to delete venue group RMS configurations"
            }
          }
        },
        "description": "This API uses OAuth2 client credentials flow via Auth0.\n**Important:** Include the `audience` parameter in your token request.\nExample token request:\n```\nPOST https://auth.bookabletech.com/oauth/token\n{\n  \"grant_type\": \"client_credentials\",\n  \"client_id\": \"YOUR_CLIENT_ID\",\n  \"client_secret\": \"YOUR_CLIENT_SECRET\",\n  \"audience\": \"api.bookabletech.com\"\n}\n```\n"
      },
      "Sandbox": {
        "type": "oauth2",
        "flows": {
          "clientCredentials": {
            "tokenUrl": "https://auth-sandbox.bookabletech.com/oauth/token",
            "scopes": {
              "venue-group:read": "Grants read access to venue group details and RMS configurations",
              "venue-group:create": "Grants permission to create venue group RMS configurations",
              "venue-group:update": "Grants permission to update venue group RMS configurations",
              "venue-group:delete": "Grants permission to delete venue group RMS configurations"
            }
          }
        },
        "description": "This API uses OAuth2 client credentials flow via Auth0 for the Sandbox environment.\nThis environment is used for partner testing with production-like data and WireMock integrations.\n**Important:** Include the `audience` parameter in your token request.\nExample token request:\n```\nPOST https://auth-sandbox.bookabletech.com/oauth/token\n{\n  \"grant_type\": \"client_credentials\",\n  \"client_id\": \"YOUR_CLIENT_ID\",\n  \"client_secret\": \"YOUR_CLIENT_SECRET\",\n  \"audience\": \"api.bookabletech.com\"\n}\n```\n"
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "Maximum number of requests allowed per window.",
        "schema": {
          "type": "integer"
        },
        "example": 200
      },
      "RateLimitRemaining": {
        "description": "Number of requests remaining in the current window.",
        "schema": {
          "type": "integer"
        },
        "example": 150
      },
      "RateLimitReset": {
        "description": "Unix timestamp (seconds since epoch) when the current rate-limit window resets.",
        "schema": {
          "type": "integer",
          "format": "int64"
        },
        "example": 1741651200
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Unauthorized - Authentication is required",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
              "title": "Invalid User Credentials",
              "status": 401,
              "detail": "The provided credentials are invalid",
              "code": "USER-N-003",
              "isRetryable": false,
              "traceId": "0HNJ2BG2TU3BU:00000002"
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc9110#section-15.5.5\"\ntitle: Invalid User Credentials\nstatus: 401\ndetail: The provided credentials are invalid\ncode: USER-N-003\nisRetryable: false\ntraceId: \"0HNJ2BG2TU3BU:00000002\"\n"
          }
        }
      },
      "TooManyRequests": {
        "description": "Too Many Requests - Rate limit exceeded. Retry after the window specified in the Retry-After header.",
        "headers": {
          "Retry-After": {
            "description": "Number of seconds to wait before retrying the request.",
            "schema": {
              "type": "integer"
            },
            "example": 60
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc6585#section-4",
              "title": "Rate Limit Exceeded",
              "status": 429,
              "detail": "Too many requests have been made in a short period. Please wait and retry.",
              "code": "RATE-R-001",
              "isRetryable": true,
              "traceId": "0HNJ2BG2TU3BU:00000006"
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc6585#section-4\"\ntitle: Rate Limit Exceeded\nstatus: 429\ndetail: Too many requests have been made in a short period. Please wait and retry.\ncode: RATE-R-001\nisRetryable: true\ntraceId: \"0HNJ2BG2TU3BU:00000006\"\n"
          }
        }
      },
      "InternalServerError": {
        "description": "Internal Server Error - An unexpected error occurred",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ServerError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc9110#section-15.6.1",
              "title": "Internal Server Error",
              "status": 500,
              "detail": "An unexpected error occurred while processing the request",
              "code": "SYS-N-001",
              "isRetryable": false,
              "traceId": "0HNJ2BG2TU3BU:00000007"
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ServerError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc9110#section-15.6.1\"\ntitle: Internal Server Error\nstatus: 500\ndetail: An unexpected error occurred while processing the request\ncode: SYS-N-001\nisRetryable: false\ntraceId: \"0HNJ2BG2TU3BU:00000007\"\n"
          }
        }
      },
      "BadRequest": {
        "description": "Bad Request - The request was invalid or cannot be served",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
              "title": "Validation Failed",
              "status": 400,
              "detail": "One or more validation errors occurred.",
              "code": "VALID-N-001",
              "isRetryable": false,
              "traceId": "0HNJ2BG2TU3BU:00000001",
              "errors": {
                "Date": [
                  "Availability date cannot be in the past."
                ]
              }
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc9110#section-15.5.1\"\ntitle: Validation Failed\nstatus: 400\ndetail: One or more validation errors occurred.\ncode: VALID-N-001\nisRetryable: false\ntraceId: \"0HNJ2BG2TU3BU:00000001\"\nerrors.Date[1]: \"Availability date cannot be in the past.\"\n"
          }
        }
      },
      "NotFound": {
        "description": "Not Found - The requested resource was not found",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc9110#section-15.5.5",
              "title": "Venue Not Found",
              "status": 404,
              "detail": "The requested venue could not be found",
              "code": "VENUE-N-001",
              "isRetryable": false,
              "traceId": "0HNJ2BG2TU3BU:00000004"
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc9110#section-15.5.5\"\ntitle: Venue Not Found\nstatus: 404\ndetail: The requested venue could not be found\ncode: VENUE-N-001\nisRetryable: false\ntraceId: \"0HNJ2BG2TU3BU:00000004\"\n"
          }
        }
      },
      "Conflict": {
        "description": "Conflict - The request conflicts with the current state of the resource",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": {
              "type": "https://tools.ietf.org/html/rfc9110#section-15.5.10",
              "title": "Email Already In Use",
              "status": 409,
              "detail": "A user with this email address already exists",
              "code": "USER-N-001",
              "isRetryable": false,
              "traceId": "0HNJ2BG2TU3BU:00000005"
            }
          },
          "text/toon": {
            "schema": {
              "$ref": "#/components/schemas/ClientError"
            },
            "example": "type: \"https://tools.ietf.org/html/rfc9110#section-15.5.10\"\ntitle: Email Already In Use\nstatus: 409\ndetail: A user with this email address already exists\ncode: USER-N-001\nisRetryable: false\ntraceId: \"0HNJ2BG2TU3BU:00000005\"\n"
          }
        }
      }
    }
  }
}