{
  "openapi": "3.1.0",
  "info": {
    "title": "Conciar API",
    "version": "1.0.0",
    "description": "The Conciar Connect API (/connect/v1, needs an API key) and the public booking API (/public/v1, no key). Documentation: https://docs.conciar.com/en/developers/"
  },
  "servers": [
    {
      "url": "https://api.conciar.com"
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key",
        "description": "Publishable (pk_…) or secret (cnct_…) key."
      },
      "customerToken": {
        "type": "http",
        "scheme": "bearer",
        "description": "Customer access token from POST /connect/v1/auth/otp/verify."
      }
    }
  },
  "paths": {
    "/connect/v1/locations": {
      "get": {
        "operationId": "connect-locations",
        "summary": "List locations",
        "description": "The organization's active sales channels, sorted by name. Delivery-platform channels (Uber Eats and the like) are left out. Use a location's sales_channel_token as the X-Sales-Channel header of every /store call. This endpoint itself needs no sales channel.\n\nholiday_hours covers the next 14 days. is_open_now is false after the last-order cutoff.",
        "tags": [
          "Connect API: Locations and reference data"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "timezone": "Europe/Amsterdam",
                    "locations": [
                      {
                        "sales_channel_token": "cnct_ch_your_channel_token",
                        "name": "Bistro Example — Centre",
                        "is_test": false,
                        "address": "Example Street 1, 1000 AA Example City",
                        "city": "Example City",
                        "latitude": 52,
                        "longitude": 4,
                        "operating_hours": {
                          "monday": {
                            "isOpen": true,
                            "is24Hours": false,
                            "timeSlots": [
                              {
                                "openTime": "11:00",
                                "closeTime": "22:00"
                              }
                            ]
                          },
                          "tuesday": {
                            "isOpen": true,
                            "is24Hours": false,
                            "timeSlots": [
                              {
                                "openTime": "11:00",
                                "closeTime": "22:00"
                              }
                            ]
                          },
                          "wednesday": {
                            "isOpen": true,
                            "is24Hours": false,
                            "timeSlots": [
                              {
                                "openTime": "11:00",
                                "closeTime": "22:00"
                              }
                            ]
                          },
                          "thursday": {
                            "isOpen": true,
                            "is24Hours": false,
                            "timeSlots": [
                              {
                                "openTime": "11:00",
                                "closeTime": "22:00"
                              }
                            ]
                          },
                          "friday": {
                            "isOpen": true,
                            "is24Hours": false,
                            "timeSlots": [
                              {
                                "openTime": "11:00",
                                "closeTime": "23:00"
                              }
                            ]
                          },
                          "saturday": {
                            "isOpen": true,
                            "is24Hours": false,
                            "timeSlots": [
                              {
                                "openTime": "12:00",
                                "closeTime": "23:00"
                              }
                            ]
                          },
                          "sunday": {
                            "isOpen": false,
                            "is24Hours": false,
                            "timeSlots": []
                          }
                        },
                        "holiday_hours": [],
                        "is_open_now": true,
                        "asap_enabled": true,
                        "lead_time_minutes": 15,
                        "slot_minutes": 15,
                        "last_order_minutes_before_close": 10,
                        "max_days_ahead": 0
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/countries": {
      "get": {
        "operationId": "connect-countries",
        "summary": "List countries",
        "description": "Every country with its ISO codes, calling prefix and address/phone formats, sorted by name. Use the id wherever a country_id is asked for.\n\nname is a lowercase key, not a display name.",
        "tags": [
          "Connect API: Locations and reference data"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "countries": [
                    {
                      "id": 150,
                      "name": "netherlands",
                      "iso_code_2": "NL",
                      "iso_code_3": "NLD",
                      "call_prefix": 31,
                      "active": true,
                      "has_state": false,
                      "has_zipcode": true,
                      "zipcode_format": "NNNN LL",
                      "phone_digits": 9,
                      "…": "…"
                    }
                  ]
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/app/init": {
      "post": {
        "operationId": "connect-app-init",
        "summary": "App start-up handshake",
        "description": "Call once per app launch or resume. Returns the server time and whether the sent bearer token belongs to a member of this organization. It never answers 401. When the merchant has app installations turned on, the install is recorded.\n\nRate limit: 30/min per key (a publishable key: per key and IP)\n\nauthenticated is true only when a bearer token is sent and belongs to a member of this organization. server_time is in the organization's timezone.",
        "tags": [
          "Connect API: Locations and reference data"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "installation_id": {
                    "type": "string",
                    "description": "Your stable id for this install, max 64."
                  },
                  "platform": {
                    "type": "string",
                    "description": "ios, android, web, macos, windows or linux."
                  },
                  "app_version": {
                    "type": "string",
                    "description": "Max 32."
                  },
                  "build_number": {
                    "type": "string",
                    "description": "Max 32."
                  },
                  "os_version": {
                    "type": "string",
                    "description": "Max 64."
                  },
                  "device_model": {
                    "type": "string",
                    "description": "Max 100."
                  },
                  "locale": {
                    "type": "string",
                    "description": "Max 20."
                  },
                  "timezone": {
                    "type": "string",
                    "description": "Max 64."
                  }
                },
                "required": [
                  "installation_id",
                  "platform",
                  "app_version"
                ]
              },
              "example": {
                "installation_id": "a1b2c3d4-example",
                "platform": "ios",
                "app_version": "1.4.0"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "server_time": "2026-10-16T11:58:12+02:00",
                    "authenticated": false
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation failed: {status: false, message, errors}."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/auth/register": {
      "post": {
        "operationId": "connect-auth-register",
        "summary": "Register a customer",
        "description": "Emails a sign-in code. The answer is the same when the address already belongs to a member (they simply get a code).\n\nRate limit: 5/min per IP",
        "tags": [
          "Connect API: Customer sign-in"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "first_name": {
                    "type": "string",
                    "description": "Max 100."
                  },
                  "last_name": {
                    "type": "string",
                    "description": "Max 100."
                  },
                  "email": {
                    "type": "string",
                    "description": "Max 255."
                  },
                  "marketing_opt_in": {
                    "type": "boolean",
                    "description": "Consent to marketing."
                  }
                },
                "required": [
                  "first_name",
                  "email"
                ]
              },
              "example": {
                "first_name": "Alex",
                "email": "alex@example.com"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "message": "We emailed you a sign-in code.",
                  "expires_in": "10 minutes"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed: {status: false, message, errors}."
          },
          "429": {
            "description": "OTP_COOLDOWN — one code per minute and five per hour per address. Body has retry_after (seconds); Retry-After header too."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/auth/otp/request": {
      "post": {
        "operationId": "connect-auth-otp-request",
        "summary": "Request a sign-in code",
        "description": "Sends a code to an existing customer. The answer is the same whether or not the address belongs to an account.\n\nRate limit: 5/min per IP",
        "tags": [
          "Connect API: Customer sign-in"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "identifier": {
                    "type": "string",
                    "description": "The email address."
                  },
                  "type": {
                    "type": "string",
                    "description": "email. (phone is accepted, but no code is delivered to a phone.)"
                  }
                },
                "required": [
                  "identifier",
                  "type"
                ]
              },
              "example": {
                "identifier": "alex@example.com",
                "type": "email"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "message": "If this belongs to an account, we sent it a sign-in code.",
                  "expires_in": "10 minutes"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed: {message, errors}."
          },
          "429": {
            "description": "OTP_COOLDOWN, with retry_after."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/auth/otp/verify": {
      "post": {
        "operationId": "connect-auth-otp-verify",
        "summary": "Verify a code and get an access token",
        "description": "Returns the customer and a personal access token (valid 6 months; there is no refresh token — sign in again when it expires).\n\nRate limit: 20/min per IP\n\nVerifying an emailed code also links earlier guest orders placed here with that email to the account; linked_orders counts them and the stamps and points they brought.",
        "tags": [
          "Connect API: Customer sign-in"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "identifier": {
                    "type": "string",
                    "description": "The email address the code was sent to."
                  },
                  "type": {
                    "type": "string",
                    "description": "email. (phone is accepted, but codes are only ever emailed.)"
                  },
                  "code": {
                    "type": "string",
                    "description": "The 6-digit code."
                  }
                },
                "required": [
                  "identifier",
                  "type",
                  "code"
                ]
              },
              "example": {
                "identifier": "alex@example.com",
                "type": "email",
                "code": "123456"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "data": {
                    "customer": {
                      "id": 4242,
                      "first_name": "Alex",
                      "last_name": null,
                      "email": "alex@example.com",
                      "organization_customer_id": 77,
                      "shipping_addresses": [],
                      "phones": []
                    },
                    "access_token": "your_customer_access_token",
                    "token_type": "Bearer",
                    "linked_orders": {
                      "count": 0,
                      "stamps": 0,
                      "points": 0,
                      "queued": 0
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "{status: false, message, attempts_remaining} — wrong, expired or used-up code."
          },
          "422": {
            "description": "Validation failed: {message, errors}."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/auth/otp/resend": {
      "post": {
        "operationId": "connect-auth-otp-resend",
        "summary": "Resend a sign-in code",
        "description": "Same parameters and answers as requesting a code; the previous code stops working.\n\nRate limit: 5/min per IP",
        "tags": [
          "Connect API: Customer sign-in"
        ],
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "identifier": {
                    "type": "string",
                    "description": "The email address."
                  },
                  "type": {
                    "type": "string",
                    "description": "email. (phone is accepted, but no code is delivered to a phone.)"
                  }
                },
                "required": [
                  "identifier",
                  "type"
                ]
              },
              "example": {
                "identifier": "alex@example.com",
                "type": "email"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "message": "If this belongs to an account, we sent it a new sign-in code.",
                  "expires_in": "10 minutes"
                }
              }
            }
          },
          "422": {
            "description": "Validation failed: {message, errors}."
          },
          "429": {
            "description": "OTP_COOLDOWN, with retry_after."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/restaurant/menu": {
      "get": {
        "operationId": "connect-restaurant-menu",
        "summary": "Get the menu",
        "description": "The menu that applies now (or the first menu when none does), with categories, items and option groups. Items not available today or not sold on this channel are left out; items sold out on this channel stay in with out_of_stock: true. Names follow Accept-Language; translations holds the other languages.\n\nOrder with an item's id (not product_id) and option ids. maximum_selections 0 means no maximum.\n\nstamp_eligible is the deprecated name of earns_stamps and always has the same value.",
        "tags": [
          "Connect API: Restaurant menu and takeaway orders"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 3,
                    "name": "All day",
                    "start_at": null,
                    "end_at": null,
                    "categories": [
                      {
                        "id": 12,
                        "code": "mains",
                        "name": "Mains",
                        "color": null,
                        "translations": {},
                        "items": [
                          {
                            "id": 101,
                            "product_id": 9001,
                            "sku": "EX-BURGER",
                            "name": "Example burger",
                            "description": null,
                            "story": null,
                            "translations": {},
                            "image_url": null,
                            "out_of_stock": false,
                            "earns_stamps": true,
                            "stamp_reward_eligible": true,
                            "stamp_eligible": true,
                            "earns_points": true,
                            "available_from": null,
                            "available_until": null,
                            "price": {
                              "amount": "12.50",
                              "minor": 1250,
                              "currency": "EUR"
                            },
                            "option_groups": [
                              {
                                "id": 40,
                                "code": "extras",
                                "name": "Extras",
                                "translations": {},
                                "is_required": false,
                                "minimum_selections": 0,
                                "maximum_selections": 3,
                                "included_selections": 0,
                                "rank": 1,
                                "options": [
                                  {
                                    "id": 501,
                                    "name": "Extra cheese",
                                    "translations": {},
                                    "is_default": false,
                                    "rank": 1,
                                    "extra_price": {
                                      "amount": "1.00",
                                      "minor": 100,
                                      "currency": "EUR"
                                    }
                                  }
                                ]
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "MENU_NOT_FOUND — the restaurant has no menu."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/restaurant/pickup-info": {
      "get": {
        "operationId": "connect-restaurant-pickup-info",
        "summary": "Get pickup hours and slots",
        "description": "Opening hours, holiday hours for the next 14 days and the pickup rules: whether ASAP is allowed, the lead time, the slot size, the last-order cutoff and how many days ahead customers may order.",
        "tags": [
          "Connect API: Restaurant menu and takeaway orders"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "store": {
                      "sales_channel_token": "cnct_ch_your_channel_token",
                      "name": "Bistro Example",
                      "address": "Example Street 1, 1000 AA Example City"
                    },
                    "timezone": "Europe/Amsterdam",
                    "operating_hours": {
                      "monday": {
                        "isOpen": true,
                        "is24Hours": false,
                        "timeSlots": [
                          {
                            "openTime": "11:00",
                            "closeTime": "22:00"
                          }
                        ]
                      },
                      "tuesday": {
                        "isOpen": true,
                        "is24Hours": false,
                        "timeSlots": [
                          {
                            "openTime": "11:00",
                            "closeTime": "22:00"
                          }
                        ]
                      },
                      "wednesday": {
                        "isOpen": true,
                        "is24Hours": false,
                        "timeSlots": [
                          {
                            "openTime": "11:00",
                            "closeTime": "22:00"
                          }
                        ]
                      },
                      "thursday": {
                        "isOpen": true,
                        "is24Hours": false,
                        "timeSlots": [
                          {
                            "openTime": "11:00",
                            "closeTime": "22:00"
                          }
                        ]
                      },
                      "friday": {
                        "isOpen": true,
                        "is24Hours": false,
                        "timeSlots": [
                          {
                            "openTime": "11:00",
                            "closeTime": "23:00"
                          }
                        ]
                      },
                      "saturday": {
                        "isOpen": true,
                        "is24Hours": false,
                        "timeSlots": [
                          {
                            "openTime": "12:00",
                            "closeTime": "23:00"
                          }
                        ]
                      },
                      "sunday": {
                        "isOpen": false,
                        "is24Hours": false,
                        "timeSlots": []
                      }
                    },
                    "holiday_hours": [],
                    "is_open_now": true,
                    "asap_enabled": true,
                    "lead_time_minutes": 15,
                    "slot_minutes": 15,
                    "last_order_minutes_before_close": 10,
                    "max_days_ahead": 0
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/restaurant/orders": {
      "post": {
        "operationId": "connect-restaurant-order-create",
        "summary": "Place a takeaway order",
        "description": "Creates the order and starts its payment. Redirect methods return payment.payment_url (send the customer there); Apple Pay and Google Pay return the wallet details to show the sheet, then charge with POST …/payment. An order fully paid by a reward or points needs no payment (payment: null). Unpaid orders expire after 30 minutes (the default).\n\nRate limit: 10/min per key (a publishable key: per key and IP); 60/min per store (organization and sales channel)\n\nKeep order_token: it is the guest's only way to read, pay or cancel the order (header X-Order-Token).\n\nstatus: awaiting_payment, scheduled, received, preparing, ready, collected or cancelled. pickup_number is set once the order is paid.\n\nFor applepay and google_pay, payment is {type: wallet, method, amount, merchant} — what the native payment sheet needs; then charge the token with POST …/payment.",
        "tags": [
          "Connect API: Restaurant menu and takeaway orders"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "1–64 characters. A retry with the same key and body within 24 hours returns the same order instead of a new one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "type": "array",
                    "description": "1–50 lines."
                  },
                  "items[].item_id": {
                    "type": "integer",
                    "description": "Menu item id."
                  },
                  "items[].qty": {
                    "type": "integer",
                    "description": "1–99, default 1."
                  },
                  "items[].options": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "description": "Option ids, up to 30, no duplicates."
                  },
                  "pickup_at": {
                    "type": "string",
                    "description": "Date-time on the slot grid; leave out for as soon as possible."
                  },
                  "customer_notes": {
                    "type": "string",
                    "description": "Max 500."
                  },
                  "customer.first_name": {
                    "type": "string",
                    "description": "Required for guests (no bearer token). Max 100."
                  },
                  "customer.last_name": {
                    "type": "string",
                    "description": "Max 100."
                  },
                  "customer.email": {
                    "type": "string",
                    "description": "Required for guests. Max 255."
                  },
                  "payment_method_key": {
                    "type": "string",
                    "description": "A key from GET /store/payment-methods, e.g. ideal, applepay."
                  },
                  "payment_service_provider_key": {
                    "type": "string",
                    "description": "Pick the provider; otherwise the first enabled one."
                  },
                  "payment_method_data": {
                    "type": "object",
                    "description": "Optional. For visa, mastercard and amex its card_token is passed to the provider."
                  },
                  "return_url": {
                    "type": "string",
                    "description": "Required except for applepay and google_pay. Where the provider sends the customer after paying. Max 2048."
                  },
                  "redeem_reward": {
                    "type": "boolean",
                    "description": "Members: spend a full stamp card."
                  },
                  "redeem_points": {
                    "type": "integer",
                    "description": "Members: spend exactly this many points (1–100000000)."
                  },
                  "use_points": {
                    "type": "boolean",
                    "description": "Members: spend as many points as allowed."
                  },
                  "phone, birth_date, billing_address": {
                    "description": "Only when the method's requires list asks for them (e.g. Klarna). phone max 30, birth_date max 10. billing_address: street (max 100), house_number (max 10), house_number_suffix (max 10), postcode (max 10), city (max 100), country (ISO-2)."
                  }
                },
                "required": [
                  "items",
                  "items[].item_id",
                  "payment_method_key"
                ]
              },
              "example": {
                "items": [
                  {
                    "item_id": 101,
                    "qty": 2,
                    "options": [
                      501
                    ]
                  }
                ],
                "customer": {
                  "first_name": "Alex",
                  "email": "alex@example.com"
                },
                "payment_method_key": "ideal",
                "return_url": "https://www.example.com/order/return"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "order": {
                      "reference": "EXAMPLE-0001",
                      "pickup_number": null,
                      "pickup_name": "Alex",
                      "store": {
                        "sales_channel_token": "cnct_ch_your_channel_token",
                        "name": "Bistro Example"
                      },
                      "status": "awaiting_payment",
                      "pickup_at": "2026-10-16T12:30:00+02:00",
                      "release_at": null,
                      "created_at": "2026-10-16T11:58:12+02:00",
                      "customer_notes": null,
                      "lines": [
                        {
                          "item_id": 101,
                          "name": "Example burger",
                          "image_url": null,
                          "qty": 2,
                          "selections": [
                            "Extra cheese"
                          ],
                          "option_ids": [
                            501
                          ],
                          "unit_price": {
                            "amount": "12.50",
                            "minor": 1250,
                            "currency": "EUR"
                          },
                          "total_price": {
                            "amount": "25.00",
                            "minor": 2500,
                            "currency": "EUR"
                          }
                        }
                      ],
                      "subtotal": {
                        "amount": "25.00",
                        "minor": 2500,
                        "currency": "EUR"
                      },
                      "discount": {
                        "amount": "0.00",
                        "minor": 0,
                        "currency": "EUR"
                      },
                      "total": {
                        "amount": "25.00",
                        "minor": 2500,
                        "currency": "EUR"
                      },
                      "reward_redeemed": false,
                      "points_redeemed": 0,
                      "points_discount": {
                        "amount": "0.00",
                        "minor": 0,
                        "currency": "EUR"
                      },
                      "loyalty": {
                        "stamps_earned": 0,
                        "points_earned": 0
                      }
                    },
                    "order_token": "ot_example_order_token",
                    "payment": {
                      "type": "redirect",
                      "payment_url": "https://payment-provider.example/checkout/…",
                      "transaction_key": "example-transaction-key"
                    }
                  }
                }
              }
            }
          },
          "409": {
            "description": "IDEMPOTENCY_KEY_REUSED (same key, different body) or IDEMPOTENCY_KEY_IN_PROGRESS."
          },
          "422": {
            "description": "Validation (including an Idempotency-Key that is empty or longer than 64), or a code in message: STORE_CLOSED, INVALID_PICKUP_TIME, ITEM_UNAVAILABLE, INVALID_OPTIONS, NO_REWARD_AVAILABLE, NO_ELIGIBLE_ITEM, INSUFFICIENT_POINTS, POINTS_DISABLED, BELOW_MIN_REDEMPTION, EXCEEDS_MAX, NOTHING_TO_PAY, PAYMENT_METHOD_UNAVAILABLE, PAYMENT_DETAILS_REQUIRED, PAYMENT_FAILED. errors points at the field."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/restaurant/orders/{reference}": {
      "get": {
        "operationId": "connect-restaurant-order-show",
        "summary": "Get an order",
        "description": "Poll this for the order status (every 5–10 seconds is plenty).\n\nRate limit: 30/min per key (a publishable key: per key and IP)\n\nSend either the bearer token of the customer who placed the order or the header X-Order-Token with the order_token returned at placement. Anything else is 404 ORDER_NOT_FOUND.",
        "tags": [
          "Connect API: Restaurant menu and takeaway orders"
        ],
        "parameters": [
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "description": "The order reference.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Order-Token",
            "in": "header",
            "required": false,
            "description": "The order_token, when there is no bearer token.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "reference": "EXAMPLE-0001",
                    "pickup_number": 17,
                    "pickup_name": "Alex",
                    "store": {
                      "sales_channel_token": "cnct_ch_your_channel_token",
                      "name": "Bistro Example"
                    },
                    "status": "preparing",
                    "pickup_at": "2026-10-16T12:30:00+02:00",
                    "release_at": null,
                    "created_at": "2026-10-16T11:58:12+02:00",
                    "customer_notes": null,
                    "lines": [
                      {
                        "item_id": 101,
                        "name": "Example burger",
                        "image_url": null,
                        "qty": 2,
                        "selections": [
                          "Extra cheese"
                        ],
                        "option_ids": [
                          501
                        ],
                        "unit_price": {
                          "amount": "12.50",
                          "minor": 1250,
                          "currency": "EUR"
                        },
                        "total_price": {
                          "amount": "25.00",
                          "minor": 2500,
                          "currency": "EUR"
                        }
                      }
                    ],
                    "subtotal": {
                      "amount": "25.00",
                      "minor": 2500,
                      "currency": "EUR"
                    },
                    "discount": {
                      "amount": "0.00",
                      "minor": 0,
                      "currency": "EUR"
                    },
                    "total": {
                      "amount": "25.00",
                      "minor": 2500,
                      "currency": "EUR"
                    },
                    "reward_redeemed": false,
                    "points_redeemed": 0,
                    "points_discount": {
                      "amount": "0.00",
                      "minor": 0,
                      "currency": "EUR"
                    },
                    "loyalty": {
                      "stamps_earned": 0,
                      "points_earned": 0
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "ORDER_NOT_FOUND."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/restaurant/orders/{reference}/payment": {
      "post": {
        "operationId": "connect-restaurant-order-payment",
        "summary": "Pay or retry payment",
        "description": "Starts a new payment for an order awaiting payment, or charges Apple Pay / Google Pay. With apple_pay_token or google_pay_token the charge happens in this call: 200 when paid, 202 when pending, 422 PAYMENT_FAILED when declined (the order stays payable).\n\nRate limit: 10/min per key (a publishable key: per key and IP); 120/min per store (shared by payment and cancel)\n\nSend either the bearer token of the customer who placed the order or the header X-Order-Token with the order_token returned at placement. Anything else is 404 ORDER_NOT_FOUND.",
        "tags": [
          "Connect API: Restaurant menu and takeaway orders"
        ],
        "parameters": [
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "description": "The order reference.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Order-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payment_method_key": {
                    "type": "string",
                    "description": "Payment method key."
                  },
                  "payment_service_provider_key": {
                    "type": "string",
                    "description": "Provider key."
                  },
                  "payment_method_data": {
                    "type": "object",
                    "description": "Optional. For visa, mastercard and amex its card_token is passed to the provider."
                  },
                  "return_url": {
                    "type": "string",
                    "description": "Required except for applepay and google_pay. Max 2048."
                  },
                  "apple_pay_token": {
                    "oneOf": [
                      {
                        "type": "object"
                      },
                      {
                        "type": "string"
                      }
                    ],
                    "description": "The PKPaymentToken (object, JSON or base64)."
                  },
                  "google_pay_token": {
                    "type": "string",
                    "description": "tokenizationData.token (JSON or base64)."
                  },
                  "customer.first_name, customer.last_name": {
                    "type": "string",
                    "description": "Max 100 each. Only for methods that require a name; defaults to the order's."
                  },
                  "phone, birth_date, billing_address": {
                    "description": "Only when the method's requires list asks for them. Same fields as when placing the order."
                  }
                },
                "required": [
                  "payment_method_key"
                ]
              },
              "example": {
                "payment_method_key": "ideal",
                "return_url": "https://www.example.com/order/return"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Wallet token charged and paid: {data: {status: \"paid\", order, payment}}."
          },
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "payment": {
                      "type": "redirect",
                      "payment_url": "https://payment-provider.example/checkout/…",
                      "transaction_key": "example-transaction-key"
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Wallet token charged, still pending at the provider: {data: {status: \"pending\", order, payment}}."
          },
          "404": {
            "description": "ORDER_NOT_FOUND."
          },
          "409": {
            "description": "PAYMENT_FAILED — another payment for this order is in progress."
          },
          "422": {
            "description": "Validation, or ORDER_NOT_PAYABLE, PAYMENT_METHOD_UNAVAILABLE, PAYMENT_DETAILS_REQUIRED, INVALID_WALLET_TOKEN or PAYMENT_FAILED (a declined wallet charge also carries data with the order)."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/restaurant/orders/{reference}/cancel": {
      "post": {
        "operationId": "connect-restaurant-order-cancel",
        "summary": "Cancel an unpaid order",
        "description": "Only while the order is awaiting payment. Releases any reward or points held for it.\n\nRate limit: 10/min per key (a publishable key: per key and IP); 120/min per store (shared by payment and cancel)\n\nSend either the bearer token of the customer who placed the order or the header X-Order-Token with the order_token returned at placement. Anything else is 404 ORDER_NOT_FOUND.",
        "tags": [
          "Connect API: Restaurant menu and takeaway orders"
        ],
        "parameters": [
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "description": "The order reference.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Order-Token",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "reference": "EXAMPLE-0001",
                    "pickup_number": null,
                    "pickup_name": "Alex",
                    "store": {
                      "sales_channel_token": "cnct_ch_your_channel_token",
                      "name": "Bistro Example"
                    },
                    "status": "cancelled",
                    "pickup_at": "2026-10-16T12:30:00+02:00",
                    "release_at": null,
                    "created_at": "2026-10-16T11:58:12+02:00",
                    "customer_notes": null,
                    "lines": [
                      {
                        "item_id": 101,
                        "name": "Example burger",
                        "image_url": null,
                        "qty": 2,
                        "selections": [
                          "Extra cheese"
                        ],
                        "option_ids": [
                          501
                        ],
                        "unit_price": {
                          "amount": "12.50",
                          "minor": 1250,
                          "currency": "EUR"
                        },
                        "total_price": {
                          "amount": "25.00",
                          "minor": 2500,
                          "currency": "EUR"
                        }
                      }
                    ],
                    "subtotal": {
                      "amount": "25.00",
                      "minor": 2500,
                      "currency": "EUR"
                    },
                    "discount": {
                      "amount": "0.00",
                      "minor": 0,
                      "currency": "EUR"
                    },
                    "total": {
                      "amount": "25.00",
                      "minor": 2500,
                      "currency": "EUR"
                    },
                    "reward_redeemed": false,
                    "points_redeemed": 0,
                    "points_discount": {
                      "amount": "0.00",
                      "minor": 0,
                      "currency": "EUR"
                    },
                    "loyalty": {
                      "stamps_earned": 0,
                      "points_earned": 0
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "ORDER_NOT_FOUND."
          },
          "422": {
            "description": "ORDER_NOT_CANCELLABLE — already paid or no longer awaiting payment."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/restaurant/table/{token}/bill-request": {
      "post": {
        "operationId": "connect-restaurant-bill-request",
        "summary": "Ask for the bill at a table",
        "description": "A guest at a table asks for the bill from their phone. The token comes from the table's QR code. Calling it again keeps the first time.\n\nRate limit: 120/min per store",
        "tags": [
          "Connect API: Restaurant menu and takeaway orders"
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The table's QR token: the table id, a dot and 24 characters.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "bill_requested_at": "2026-10-16T21:14:03+02:00"
                }
              }
            }
          },
          "404": {
            "description": "Unknown table (or a table of another organization)."
          },
          "422": {
            "description": "{status: false, message: \"This table has no open visit.\"}"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/restaurant/table/{token}/assistance-request": {
      "post": {
        "operationId": "connect-restaurant-assistance-request",
        "summary": "Call a waiter to a table",
        "description": "A guest at a table calls a waiter from their phone. The token comes from the table's QR code. Waiters see the call until one of them handles it.\n\nRate limit: 120/min per store\n\nUnlike the bill request, it does not need an open visit at the table.",
        "tags": [
          "Connect API: Restaurant menu and takeaway orders"
        ],
        "parameters": [
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The table's QR token: the table id, a dot and 24 characters.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "assistance_requested_at": "2026-10-16T21:14:03+02:00"
                }
              }
            }
          },
          "404": {
            "description": "Unknown table (or a table of another organization)."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/profile": {
      "get": {
        "operationId": "connect-customer-profile",
        "summary": "Get the profile",
        "description": "member_reference is the value to show as the membership QR code.",
        "tags": [
          "Connect API: Customer account"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 4242,
                    "first_name": "Alex",
                    "last_name": "Example",
                    "email": "alex@example.com",
                    "member_since": "2026-03-01T10:00:00+01:00",
                    "member_reference": "M-EXAM-PLE0-0000",
                    "marketing_opt_in": false
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_A_MEMBER — the customer is not a member of this organization."
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/loyalty": {
      "get": {
        "operationId": "connect-customer-loyalty",
        "summary": "Get points, stamps and history",
        "description": "The points balance and its value, the stamp card, the programme rules and the last 20 loyalty events.",
        "tags": [
          "Connect API: Customer account"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "member_reference": "M-EXAM-PLE0-0000",
                    "points": {
                      "enabled": true,
                      "balance": 120,
                      "value": {
                        "amount": "1.20",
                        "minor": 120,
                        "currency": "EUR"
                      },
                      "point_value": 0.01,
                      "min_redemption": 100,
                      "max_redemption_pct": 50,
                      "can_redeem": true,
                      "earn_rate": 1,
                      "earn_on": "gross",
                      "qualifying": {
                        "scope": "all",
                        "category_ids": [],
                        "item_ids": null
                      },
                      "boosts": []
                    },
                    "stamps": {
                      "enabled": true,
                      "count": 4,
                      "per_reward": 10,
                      "rewards_available": 0,
                      "title": "Coffee card",
                      "description": null,
                      "…": "…"
                    },
                    "history": [
                      {
                        "id": 1,
                        "type": "points_earned",
                        "stamps": 0,
                        "points": 25,
                        "order_reference": "EXAMPLE-0001",
                        "created_at": "2026-10-10T12:31:00+02:00"
                      }
                    ]
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_A_MEMBER."
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/deals": {
      "get": {
        "operationId": "connect-customer-deals",
        "summary": "List deals",
        "description": "Promotions that apply on this channel now (no code needed) and the personal coupons assigned to this member.",
        "tags": [
          "Connect API: Customer account"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": "promo_12",
                      "title": "2 for 1 on Tuesdays",
                      "description": null,
                      "item_id": 101,
                      "coupon_code": null,
                      "valid_until": null
                    },
                    {
                      "id": "coupon_8",
                      "title": "Welcome gift",
                      "description": null,
                      "item_id": null,
                      "coupon_code": "WELCOME-EXAMPLE",
                      "valid_until": "2026-12-31T23:59:59+01:00"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "NOT_A_MEMBER."
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/restaurant/orders": {
      "get": {
        "operationId": "connect-customer-restaurant-orders",
        "summary": "List takeaway orders",
        "description": "The customer's app and takeaway orders, newest first, paginated.",
        "tags": [
          "Connect API: Customer account"
        ],
        "parameters": [
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "1–50, default 20.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "reference": "EXAMPLE-0001",
                      "pickup_number": null,
                      "pickup_name": "Alex",
                      "store": {
                        "sales_channel_token": "cnct_ch_your_channel_token",
                        "name": "Bistro Example"
                      },
                      "status": "awaiting_payment",
                      "pickup_at": "2026-10-16T12:30:00+02:00",
                      "release_at": null,
                      "created_at": "2026-10-16T11:58:12+02:00",
                      "customer_notes": null,
                      "lines": [
                        {
                          "item_id": 101,
                          "name": "Example burger",
                          "image_url": null,
                          "qty": 2,
                          "selections": [
                            "Extra cheese"
                          ],
                          "option_ids": [
                            501
                          ],
                          "unit_price": {
                            "amount": "12.50",
                            "minor": 1250,
                            "currency": "EUR"
                          },
                          "total_price": {
                            "amount": "25.00",
                            "minor": 2500,
                            "currency": "EUR"
                          }
                        }
                      ],
                      "subtotal": {
                        "amount": "25.00",
                        "minor": 2500,
                        "currency": "EUR"
                      },
                      "discount": {
                        "amount": "0.00",
                        "minor": 0,
                        "currency": "EUR"
                      },
                      "total": {
                        "amount": "25.00",
                        "minor": 2500,
                        "currency": "EUR"
                      },
                      "reward_redeemed": false,
                      "points_redeemed": 0,
                      "points_discount": {
                        "amount": "0.00",
                        "minor": 0,
                        "currency": "EUR"
                      },
                      "loyalty": {
                        "stamps_earned": 0,
                        "points_earned": 0
                      }
                    }
                  ],
                  "links": {
                    "first": "…",
                    "last": "…",
                    "prev": null,
                    "next": null
                  },
                  "meta": {
                    "current_page": 1,
                    "from": 1,
                    "last_page": 1,
                    "per_page": 20,
                    "to": 1,
                    "total": 1,
                    "…": "…"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/orders": {
      "get": {
        "operationId": "connect-customer-orders",
        "summary": "List store orders",
        "description": "The customer's orders with this organization, newest first. Each order has its status, currency, lines (with prices and taxes) and order prices. Internal fields, such as staff notes, are never included.\n\nA customer who is not a member gets {\"orders\": []}.",
        "tags": [
          "Connect API: Customer account"
        ],
        "parameters": [
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Default 10.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "orders": {
                    "current_page": 1,
                    "data": [
                      {
                        "id": 1,
                        "reference": "ORD-EXAMPLE00001",
                        "status": {
                          "name": "paid"
                        },
                        "currency": {
                          "symbol": "EUR"
                        },
                        "lines": [
                          "…"
                        ],
                        "prices": [
                          "…"
                        ],
                        "created_at": "2026-10-10T10:00:00.000000Z",
                        "…": "…"
                      }
                    ],
                    "per_page": 10,
                    "total": 1,
                    "…": "…"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/orders/{reference}": {
      "get": {
        "operationId": "connect-customer-order-show",
        "summary": "Get a store order",
        "description": "One order with its addresses, lines, invoice and payment transactions (key, amount, status, method, paid_at), and credit notes.",
        "tags": [
          "Connect API: Customer account"
        ],
        "parameters": [
          {
            "name": "reference",
            "in": "path",
            "required": true,
            "description": "The order reference.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "order": {
                    "reference": "ORD-EXAMPLE00001",
                    "status": {
                      "name": "paid"
                    },
                    "shipping_address": {
                      "…": "…"
                    },
                    "lines": [
                      "…"
                    ],
                    "invoice": {
                      "transactions": [
                        "…"
                      ]
                    },
                    "…": "…"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found, or not this customer's order with this organization."
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/config": {
      "get": {
        "operationId": "connect-store-config",
        "summary": "Get channel settings",
        "description": "The sales channel's settings, merged over the defaults: guest checkout, pricing mode (snapshot or live), coupon stacking, hide-out-of-stock, supported countries, enabled payment methods, subscription options and restaurant pickup settings. Keys are camelCase. Back-office settings (the maintenance IP allow-list, abandoned-cart timing, dynamic pricing, receipt printing, subscription fulfilment, capture policy) are not included.",
        "tags": [
          "Connect API: Store catalogue"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "config": {
                    "active": true,
                    "maintenanceMode": false,
                    "guestCheckout": true,
                    "cartPricing": "snapshot",
                    "couponsStackable": false,
                    "hideOutOfStock": false,
                    "supportedCountries": [],
                    "paymentMethodsMode": "organization",
                    "…": "…"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/categories": {
      "get": {
        "operationId": "connect-store-categories",
        "summary": "List categories",
        "description": "Top-level categories with their direct children and how many products in this channel each holds.",
        "tags": [
          "Connect API: Store catalogue"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": [
                    {
                      "id": 1,
                      "parent_id": null,
                      "slug": "coffee",
                      "name": "Coffee",
                      "description": null,
                      "product_count": 12,
                      "children": [
                        {
                          "id": 2,
                          "parent_id": 1,
                          "slug": "beans",
                          "name": "Beans",
                          "description": null,
                          "product_count": 8
                        }
                      ]
                    }
                  ]
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/products": {
      "get": {
        "operationId": "connect-store-products",
        "summary": "List products",
        "description": "Active products in this channel, paginated. Each product comes with its type, variants, stock, retail_price, tax breakdown and, when a currency is known, converted_retail_price. stock holds track_stock and available. Only storefront fields are returned: no cost prices and no other sales channels.",
        "tags": [
          "Connect API: Store catalogue"
        ],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Search, max 100.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Category id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Comma-separated product types, e.g. physical,digital.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "recommended, price_asc, price_desc or newest.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "1–100, default 20.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page number.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "featured, subscription",
            "in": "query",
            "required": false,
            "description": "true: only featured (in this channel) / only subscription products; false: only the others.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "price_min, price_max",
            "in": "query",
            "required": false,
            "description": "In the request currency.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "property[key]",
            "in": "query",
            "required": false,
            "description": "Filter on a product property; values come from /store/products/filters.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "current_page": 1,
                    "data": [
                      {
                        "id": 9001,
                        "sku": "EX-BEANS-1KG",
                        "type": {
                          "name": "physical"
                        },
                        "active": true,
                        "out_of_stock": false,
                        "featured": false,
                        "resolved_info": {
                          "name": "Example beans 1 kg",
                          "…": "…"
                        },
                        "retail_price": {
                          "amount": "24.95",
                          "…": "…"
                        },
                        "tax": {
                          "net": 22.89,
                          "tax_total": 2.06,
                          "gross": 24.95,
                          "…": "…"
                        },
                        "variants": [],
                        "…": "…"
                      }
                    ],
                    "per_page": 20,
                    "total": 1,
                    "…": "…"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/products/filters": {
      "get": {
        "operationId": "connect-store-product-filters",
        "summary": "List product filters",
        "description": "The property filters for the current product selection, with counts. Takes the same query parameters as the product list.",
        "tags": [
          "Connect API: Store catalogue"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "filters": [
                    {
                      "key": "roast",
                      "label": "Roast",
                      "options": [
                        {
                          "value": "dark",
                          "count": 5
                        },
                        {
                          "value": "light",
                          "count": 3
                        }
                      ]
                    }
                  ]
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/products/{id}": {
      "get": {
        "operationId": "connect-store-product-show",
        "summary": "Get a product",
        "description": "One product with its translations, categories, price rules and variants (with their options).\n\nAny active product of the organization is returned; it is not checked against this sales channel.",
        "tags": [
          "Connect API: Store catalogue"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Product id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "id": 9001,
                    "sku": "EX-BEANS-1KG",
                    "resolved_info": {
                      "name": "Example beans 1 kg",
                      "…": "…"
                    },
                    "categories": [
                      "…"
                    ],
                    "variants": [
                      "…"
                    ],
                    "…": "…"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found or inactive."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/cart/init": {
      "post": {
        "operationId": "connect-cart-init",
        "summary": "Create a cart",
        "description": "Rate limit: 30/min per key",
        "tags": [
          "Connect API: Cart and checkout"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "data": {
                    "cart_token": "example_cart_token",
                    "cart": {
                      "cart_token": "example_cart_token",
                      "items": [],
                      "totals": {
                        "subtotal": 0,
                        "discount": 0,
                        "promotion_discount": 0,
                        "total": 0,
                        "…": "…"
                      },
                      "…": "…"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/cart/sync": {
      "post": {
        "operationId": "connect-cart-sync",
        "summary": "Set cart lines and coupons",
        "description": "Declarative: quantities are set, not added, and the coupons you send replace the current ones (send none to clear). A line's price is fixed when it is first added.\n\nRate limit: 120/min per key",
        "tags": [
          "Connect API: Cart and checkout"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "cart_token": {
                    "type": "string",
                    "description": "The cart."
                  },
                  "items[].product_id": {
                    "type": "integer",
                    "description": "Product id (required when items is sent)."
                  },
                  "items[].product_variant_id": {
                    "type": "integer",
                    "description": "Variant of that product (ignored when it belongs to another product)."
                  },
                  "items[].quantity": {
                    "type": "integer",
                    "description": "Min 0; 0 removes the line (required when items is sent)."
                  },
                  "items[].purchase_type": {
                    "type": "string",
                    "description": "one_time (default) or subscription."
                  },
                  "items[].metadata": {
                    "type": "object",
                    "description": "Your own data for the line."
                  },
                  "coupon_codes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "All coupons for the cart; an empty list clears them."
                  },
                  "coupon_code": {
                    "type": "string",
                    "description": "One coupon instead of coupon_codes (ignored when coupon_codes is sent)."
                  },
                  "organization_customer_id": {
                    "type": "integer",
                    "description": "Link the cart to a member."
                  }
                },
                "required": [
                  "cart_token",
                  "items[].product_id",
                  "items[].quantity"
                ]
              },
              "example": {
                "cart_token": "example_cart_token",
                "items": [
                  {
                    "product_id": 9001,
                    "quantity": 2
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "cart": {
                    "cart_token": "example_cart_token",
                    "items": [
                      {
                        "product_id": 9001,
                        "quantity": 2,
                        "promotion_discount": 0,
                        "promotions": [],
                        "line_total": 49.9,
                        "…": "…"
                      }
                    ],
                    "totals": {
                      "subtotal": 49.9,
                      "discount": 0,
                      "promotion_discount": 0,
                      "total": 49.9,
                      "currency_id": 1,
                      "coupons": [],
                      "promotions": [],
                      "free_shipping": null
                    },
                    "…": "…"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Cart not found or no longer active."
          },
          "422": {
            "description": "Validation, an invalid or expired coupon, or more than one coupon on a channel without stacking."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/cart/{cart_token}": {
      "get": {
        "operationId": "connect-cart-show",
        "summary": "Get a cart",
        "description": "",
        "tags": [
          "Connect API: Cart and checkout"
        ],
        "parameters": [
          {
            "name": "cart_token",
            "in": "path",
            "required": true,
            "description": "The token from POST /store/cart/init.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "cart": {
                    "cart_token": "example_cart_token",
                    "items": [
                      "…"
                    ],
                    "totals": {
                      "…": "…"
                    },
                    "…": "…"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown, converted or expired cart."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/cart/{cart_token}/checkout-check": {
      "get": {
        "operationId": "connect-cart-checkout-check",
        "summary": "Check a cart before checkout",
        "description": "Blocking issues per line (unavailable, not_in_channel, out_of_stock, insufficient_stock, variant_unavailable), price changes on live-pricing channels, and coupons that no longer apply.\n\nissues[]: {sku, name, type} (insufficient_stock adds available). warnings[]: {sku, name, original_price, new_price, currency}. coupon_warnings[]: {code, reason}.",
        "tags": [
          "Connect API: Cart and checkout"
        ],
        "parameters": [
          {
            "name": "cart_token",
            "in": "path",
            "required": true,
            "description": "The token from POST /store/cart/init.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "can_proceed": true,
                  "issues": [],
                  "has_changes": false,
                  "warnings": [],
                  "coupon_warnings": []
                }
              }
            }
          },
          "404": {
            "description": "Unknown, converted or expired cart."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/cart/{cart_token}/shipping-methods": {
      "post": {
        "operationId": "connect-cart-shipping-methods",
        "summary": "Shipping methods for a cart",
        "description": "Rate limit: 120/min per key\n\nWhen nothing ships to the address the answer is still 200: shipping_methods is [] with a message.",
        "tags": [
          "Connect API: Cart and checkout"
        ],
        "parameters": [
          {
            "name": "cart_token",
            "in": "path",
            "required": true,
            "description": "The token from POST /store/cart/init.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "country_code": {
                    "type": "string",
                    "description": "ISO-2."
                  },
                  "postal_code": {
                    "type": "string",
                    "description": "Max 20."
                  },
                  "province, city, district": {
                    "type": "string",
                    "description": "Max 100 each."
                  }
                },
                "required": [
                  "country_code"
                ]
              },
              "example": {
                "country_code": "NL",
                "postal_code": "1000 AA"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "shipping_methods": [
                    {
                      "id": 3,
                      "type": "flat_rate",
                      "sort_order": 1,
                      "is_free": false,
                      "carrier": null,
                      "delivery_type": "delivery",
                      "resolved_info": {
                        "name": "Standard",
                        "description": null
                      },
                      "rate": {
                        "amount": 4.95,
                        "display_price": "€ 4,95",
                        "currency": {
                          "symbol": "EUR",
                          "…": "…"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Unknown, converted or expired cart."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/cart/{cart_token}/payment-methods": {
      "post": {
        "operationId": "connect-cart-payment-methods",
        "summary": "Payment methods for a cart",
        "description": "Methods that accept the cart amount. A cart with subscription lines only gets methods that support recurring payments.\n\nRate limit: 120/min per key\n\nThe amount checked is the cart in the X-Currency currency (else EUR). When no method fits the answer is still 200: payment_methods is [] with a message.",
        "tags": [
          "Connect API: Cart and checkout"
        ],
        "parameters": [
          {
            "name": "cart_token",
            "in": "path",
            "required": true,
            "description": "The token from POST /store/cart/init.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "shipping_method_id": {
                    "type": "integer",
                    "description": "Chosen shipping method (an existing id)."
                  },
                  "country_id": {
                    "type": "integer",
                    "description": "Country id from GET /countries."
                  }
                },
                "required": []
              },
              "example": {
                "shipping_method_id": 3
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "payment_methods": [
                    {
                      "id": 1,
                      "key": "ideal",
                      "type": "redirect",
                      "name": "iDEAL",
                      "logo": "…",
                      "status": "live",
                      "fixed_fee": null,
                      "fixed_percentage": 0,
                      "requires": [],
                      "payment_service_provider_id": 2,
                      "payment_service_provider_key": "example_psp",
                      "min_amount": null,
                      "max_amount": null
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "Unknown, converted or expired cart."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/payment-methods": {
      "get": {
        "operationId": "connect-payment-methods",
        "summary": "List payment methods",
        "description": "The payment methods enabled for the organization, narrowed to the channel's own selection when it has one. type is wallet (Apple Pay, Google Pay) or redirect; requires lists the customer details a method needs (name, email, phone, billing_address, birth_date).",
        "tags": [
          "Connect API: Cart and checkout"
        ],
        "parameters": [
          {
            "name": "amount",
            "in": "query",
            "required": false,
            "description": "0–99999999, in the channel currency. Drop methods whose minimum or maximum excludes this amount.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "recurring",
            "in": "query",
            "required": false,
            "description": "Only methods that support recurring payments.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "payment_methods": [
                    {
                      "id": 1,
                      "key": "ideal",
                      "type": "redirect",
                      "name": "iDEAL",
                      "logo": "…",
                      "status": "live",
                      "supports_recurrent": false,
                      "requires": [],
                      "payment_service_provider_id": 2,
                      "payment_service_provider_key": "example_psp",
                      "min_amount": null,
                      "max_amount": null
                    }
                  ],
                  "currency": "EUR"
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/shipping/locations": {
      "get": {
        "operationId": "connect-shipping-locations",
        "summary": "Find pickup points",
        "description": "PostNL pickup points near a postcode. Only when the merchant has PostNL enabled.",
        "tags": [
          "Connect API: Cart and checkout"
        ],
        "parameters": [
          {
            "name": "country_code",
            "in": "query",
            "required": true,
            "description": "ISO-2.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "postal_code",
            "in": "query",
            "required": true,
            "description": "Max 16.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "locations": [
                    {
                      "code": "123456",
                      "name": "Example pickup point",
                      "distance": 350,
                      "latitude": 52,
                      "longitude": 4,
                      "address": {
                        "…": "…"
                      },
                      "delivery_options": [
                        "PG"
                      ],
                      "opening_hours": {
                        "Monday": [
                          "09:00-18:00"
                        ]
                      }
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "No shipping carrier is available."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/shipping/delivery-options": {
      "get": {
        "operationId": "connect-shipping-delivery-options",
        "summary": "Delivery timeframes",
        "description": "PostNL daytime delivery windows from tomorrow up to seven days ahead.",
        "tags": [
          "Connect API: Cart and checkout"
        ],
        "parameters": [
          {
            "name": "country_code",
            "in": "query",
            "required": true,
            "description": "ISO-2.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "postal_code",
            "in": "query",
            "required": true,
            "description": "Max 16.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "house_number",
            "in": "query",
            "required": true,
            "description": "Max 16.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "delivery_options": [
                    {
                      "date": "2026-10-17",
                      "timeframes": [
                        {
                          "from": "09:00:00",
                          "to": "12:00:00",
                          "options": [
                            "Daytime"
                          ]
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "No shipping carrier is available."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/orders": {
      "post": {
        "operationId": "connect-store-order-create",
        "summary": "Place a webshop order",
        "description": "Turns a cart into an order and starts the payment. Redirect methods return payment_url; with an Apple Pay or Google Pay token the charge happens in this call. Customer details are required unless a bearer token is sent or the channel allows guest checkout.\n\nWith a wallet token, payment is {type: wallet, method, status (paid or pending), transaction_key} and payment_url is left out.\n\nprice_warnings is added when a live-pricing channel repriced a line at checkout.",
        "tags": [
          "Connect API: Cart and checkout"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "cart_token": {
                    "type": "string",
                    "description": "An active cart with items."
                  },
                  "shipping_method_id": {
                    "type": "integer",
                    "description": "From the cart's shipping methods."
                  },
                  "payment_method_key": {
                    "type": "string",
                    "description": "Payment method key."
                  },
                  "payment_service_provider_key": {
                    "type": "string",
                    "description": "Provider key."
                  },
                  "return_url": {
                    "type": "string",
                    "description": "A URL. Required except for applepay and google_pay."
                  },
                  "shipping_address": {
                    "type": "object",
                    "description": "city (max 100) and country_id required; street (max 255), house_number (max 20), apartment (max 20), zipcode (max 20), district (max 100), state (max 100) optional."
                  },
                  "billing_address": {
                    "type": "object",
                    "description": "Same fields (city and country_id required when sent); defaults to the shipping address."
                  },
                  "customer": {
                    "type": "object",
                    "description": "Required (with email) unless a bearer token is sent or the channel allows guest checkout. email (max 255), first_name, last_name (max 100 each), phone {number (max 20), country_id}."
                  },
                  "customer_notes": {
                    "type": "string",
                    "description": "Max 1000."
                  },
                  "internal_notes": {
                    "type": "string",
                    "description": "Max 1000. A note for the merchant's staff; never shown to the customer."
                  },
                  "pickup_location_code": {
                    "type": "string",
                    "description": "A pickup point code (a number is accepted). Max 32."
                  },
                  "apple_pay_token, google_pay_token": {
                    "oneOf": [
                      {
                        "type": "object"
                      },
                      {
                        "type": "string"
                      }
                    ],
                    "description": "Wallet token for an immediate charge (object, JSON or base64). payment_data is still accepted as the older name of google_pay_token."
                  },
                  "card_token": {
                    "type": "string",
                    "description": "For visa, mastercard and amex: a card token passed to the provider."
                  }
                },
                "required": [
                  "cart_token",
                  "shipping_method_id",
                  "payment_method_key",
                  "payment_service_provider_key",
                  "shipping_address"
                ]
              },
              "example": {
                "cart_token": "example_cart_token",
                "shipping_method_id": 3,
                "payment_method_key": "ideal",
                "payment_service_provider_key": "example_psp",
                "return_url": "https://shop.example.com/checkout/return",
                "customer": {
                  "email": "alex@example.com",
                  "first_name": "Alex"
                },
                "shipping_address": {
                  "street": "Example Street",
                  "house_number": "1",
                  "zipcode": "1000 AA",
                  "city": "Example City",
                  "country_id": 150
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "order": {
                    "reference": "ORD-EXAMPLE00001",
                    "…": "…"
                  },
                  "invoice": {
                    "…": "…"
                  },
                  "transaction": {
                    "…": "…"
                  },
                  "payment_url": "https://payment-provider.example/checkout/…",
                  "transaction_key": "example-transaction-key",
                  "payment": {
                    "type": "redirect",
                    "payment_url": "https://payment-provider.example/checkout/…",
                    "transaction_key": "example-transaction-key"
                  }
                }
              }
            }
          },
          "404": {
            "description": "The shipping method is inactive or belongs to another organization."
          },
          "422": {
            "description": "Validation (cart, stock, coupon, address problems), a shipping method or payment method not available for this order, or {status: false, message} with PAYMENT_METHOD_UNAVAILABLE (with reason and limit), INVALID_WALLET_TOKEN or PAYMENT_FAILED (a declined wallet charge; nothing is kept and the cart stays open)."
          },
          "500": {
            "description": "The provider could not start a redirect payment; nothing is kept."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/payment/{transaction_key}/status": {
      "get": {
        "operationId": "connect-payment-status",
        "summary": "Check a payment",
        "description": "Call this when the customer comes back on your return_url. A pending payment is checked live with the provider.\n\nRate limit: 60/min per key (a publishable key: per key and IP)",
        "tags": [
          "Connect API: Cart and checkout"
        ],
        "parameters": [
          {
            "name": "transaction_key",
            "in": "path",
            "required": true,
            "description": "From the order response.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "transaction_key": "example-transaction-key",
                  "status": "paid",
                  "is_paid": true,
                  "is_pending": false,
                  "is_failed": false,
                  "amount": "49.90",
                  "order_reference": "ORD-EXAMPLE00001"
                }
              }
            }
          },
          "404": {
            "description": "Unknown transaction."
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions": {
      "get": {
        "operationId": "connect-subscriptions-list",
        "summary": "List subscriptions",
        "description": "A customer who is not a member gets {\"subscriptions\": []}.",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "subscriptions": [
                    {
                      "id": 31,
                      "status": {
                        "name": "active",
                        "color": "#10B981"
                      },
                      "quantity": 1,
                      "next_billing_at": "2026-11-01T00:00:00.000000Z",
                      "skip_count": 0,
                      "product": {
                        "…": "…"
                      },
                      "cycles_count": 4,
                      "…": "…"
                    }
                  ]
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions/{id}": {
      "get": {
        "operationId": "connect-subscription-show",
        "summary": "Get a subscription",
        "description": "",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The subscription id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "subscription": {
                    "id": 31,
                    "status": {
                      "name": "active"
                    },
                    "…": "…"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not found for this customer."
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions/{id}/skip": {
      "post": {
        "operationId": "connect-subscription-skip",
        "summary": "Skip renewals",
        "description": "Active subscriptions only.",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The subscription id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "times": {
                    "type": "integer",
                    "description": "1–12 renewals to skip."
                  }
                },
                "required": [
                  "times"
                ]
              },
              "example": {
                "times": 1
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "subscription": {
                    "…": "…"
                  },
                  "message": "The next 1 renewal(s) will be skipped."
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions/{id}/unskip": {
      "post": {
        "operationId": "connect-subscription-unskip",
        "summary": "Undo skips",
        "description": "Active subscriptions only.",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The subscription id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "times": {
                    "type": "integer",
                    "description": "At least 1: how many to remove; all when left out."
                  }
                },
                "required": []
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "subscription": {
                    "…": "…"
                  },
                  "message": "All pending skips have been removed."
                }
              }
            }
          },
          "422": {
            "description": "This subscription has no pending skips."
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions/{id}/pause": {
      "post": {
        "operationId": "connect-subscription-pause",
        "summary": "Pause",
        "description": "Active subscriptions only.",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The subscription id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "subscription": {
                    "…": "…"
                  },
                  "message": "Your subscription has been paused."
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions/{id}/resume": {
      "post": {
        "operationId": "connect-subscription-resume",
        "summary": "Resume",
        "description": "Paused subscriptions only. A new period starts today; nothing is charged now.",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The subscription id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "subscription": {
                    "…": "…"
                  },
                  "message": "Your subscription has been resumed. Next billing on 2026-11-16."
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions/{id}/cancel": {
      "post": {
        "operationId": "connect-subscription-cancel",
        "summary": "Cancel",
        "description": "Active or paused subscriptions.",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The subscription id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "cancellation_reason": {
                    "type": "string",
                    "description": "Max 500."
                  }
                },
                "required": []
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "subscription": {
                    "…": "…"
                  },
                  "message": "Your subscription has been cancelled."
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions/{id}/swap-options": {
      "get": {
        "operationId": "connect-subscription-swap-options",
        "summary": "Products to swap to",
        "description": "Other subscription products in this channel ({products: […]}), or, when the channel only allows variant swaps, the other in-stock variants of the same product ({variants: […]}). Needs product swapping turned on for the channel; active or paused subscriptions.",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The subscription id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "products": [
                    {
                      "id": 9002,
                      "…": "…"
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "{message, errors} — product swap is not enabled for this channel, or the subscription is not found or not active."
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions/{id}/swap": {
      "post": {
        "operationId": "connect-subscription-swap",
        "summary": "Swap product",
        "description": "",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The subscription id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "product_id": {
                    "type": "integer",
                    "description": "The new product (required for product swaps): an active subscription product in this channel."
                  },
                  "product_variant_id": {
                    "type": "integer",
                    "description": "The new variant (required for variant-only swaps; optional with product_id). Must be active and in stock."
                  }
                },
                "required": []
              },
              "example": {
                "product_id": 9002
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "subscription": {
                    "…": "…"
                  },
                  "message": "Your subscription product has been updated."
                }
              }
            }
          },
          "422": {
            "description": "{message, errors} — swap not enabled, subscription not found or not active, or the product / variant not available or already the current one."
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions/{id}/payment-method": {
      "post": {
        "operationId": "connect-subscription-payment-method",
        "summary": "Change payment method",
        "description": "Starts a mandate payment of the smallest unit of the currency (e.g. € 0.01). Send the customer to payment_url.",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The subscription id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payment_service_provider_id": {
                    "type": "integer",
                    "description": "Provider id (payment_service_provider_id from the payment methods)."
                  },
                  "payment_method_id": {
                    "type": "integer",
                    "description": "Method id (id from the payment methods)."
                  },
                  "return_url": {
                    "type": "string",
                    "description": "A URL."
                  }
                },
                "required": [
                  "payment_service_provider_id",
                  "payment_method_id",
                  "return_url"
                ]
              },
              "example": {
                "payment_service_provider_id": 2,
                "payment_method_id": 1,
                "return_url": "https://shop.example.com/account"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "payment_url": "https://payment-provider.example/checkout/…",
                  "transaction_key": "example-transaction-key",
                  "transaction": {
                    "transaction_key": "example-transaction-key",
                    "amount": "0.01",
                    "payment_url": "https://payment-provider.example/checkout/…",
                    "status": {
                      "name": "pending",
                      "color": "#F59E0B"
                    },
                    "…": "…"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown subscription (or not active or paused), provider or method."
          },
          "422": {
            "description": "Validation, or the payment could not be started."
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions/{id}/shipping-methods": {
      "post": {
        "operationId": "connect-subscription-shipping-methods",
        "summary": "Shipping methods for a subscription",
        "description": "Active or paused subscriptions. Availability and cost use the subscription's renewal subtotal.",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The subscription id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "country_code": {
                    "type": "string",
                    "description": "ISO-2."
                  },
                  "postal_code": {
                    "type": "string",
                    "description": "Max 20."
                  },
                  "province, city, district": {
                    "type": "string",
                    "description": "Max 100 each."
                  }
                },
                "required": [
                  "country_code"
                ]
              },
              "example": {
                "country_code": "NL"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "shipping_methods": [
                    {
                      "id": 3,
                      "type": "flat_rate",
                      "is_free": false,
                      "…": "…"
                    }
                  ]
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/connect/v1/store/customer/subscriptions/{id}/shipping": {
      "post": {
        "operationId": "connect-subscription-shipping",
        "summary": "Change shipping",
        "description": "Replaces the shipping method and addresses for future renewals.",
        "tags": [
          "Connect API: Customer subscriptions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The subscription id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "X-Sales-Channel",
            "in": "header",
            "required": true,
            "description": "The sales channel token (cnct_ch_…).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "shipping_method_id": {
                    "type": "integer",
                    "description": "A shipping method of this organization."
                  },
                  "shipping_address": {
                    "type": "object",
                    "description": "street, house_number, city, zipcode and country_id required; apartment, district, state optional."
                  },
                  "billing_address": {
                    "type": "object",
                    "description": "Same fields (not validated); defaults to the shipping address."
                  }
                },
                "required": [
                  "shipping_method_id",
                  "shipping_address"
                ]
              },
              "example": {
                "shipping_method_id": 3,
                "shipping_address": {
                  "street": "Example Street",
                  "house_number": "1",
                  "city": "Example City",
                  "zipcode": "1000 AA",
                  "country_id": 150
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "subscription": {
                    "…": "…"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown subscription (or not active or paused) or shipping method."
          },
          "422": {
            "description": "Validation, or the selected shipping method is not available for this address."
          }
        },
        "security": [
          {
            "apiKey": [],
            "customerToken": []
          }
        ]
      }
    },
    "/public/v1/restaurants/{organization_guid}": {
      "get": {
        "operationId": "public-restaurant-show",
        "summary": "Get booking settings",
        "description": "Whether the restaurant takes online bookings (available, and a reason when not: NO_RESTAURANT, RESERVATIONS_OFF or NO_TABLES), the restaurant details, the booking window and party limits, deposit and no-show settings, and links to the hosted booking page. Also returns the booking page texts (t, tp) in the chosen language.\n\nRate limit: 120/min per restaurant and IP\n\nA restaurant that takes no online bookings still answers 200, with available: false and the reason. booking.deposit_per_person is money {amount, minor, currency} or null; booking.no_show_protection is null, none, deposit or guarantee; links.events is null when there are no ticketed events.",
        "tags": [
          "Public booking API: Restaurant and countries"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "en, nl, de, fr or es. Falls back to Accept-Language, then the restaurant's language, then en.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "available": true,
                  "reason": null,
                  "locale": "en",
                  "locales": [
                    "en",
                    "nl",
                    "de",
                    "fr",
                    "es"
                  ],
                  "restaurant": {
                    "guid": "00000000000000000",
                    "handle": "bistro-example",
                    "name": "Bistro Example",
                    "logo": null,
                    "accent": "#1f6f5c",
                    "address": "Example Street 1, 1000 AA Example City",
                    "phone": null,
                    "email": "hello@example.com",
                    "country_id": 150
                  },
                  "booking": {
                    "max_party": 8,
                    "party_cap": 20,
                    "first_day": "2026-10-16",
                    "last_day": "2027-01-14",
                    "hold_minutes": 30,
                    "deposit_per_person": null,
                    "no_show_protection": null,
                    "free_cancellation_hours": 24
                  },
                  "links": {
                    "booking_page": "https://r.conciar.com/bistro-example?lang=en",
                    "events": "https://r.conciar.com/bistro-example/events?lang=en"
                  },
                  "gift_cards": {
                    "enabled": false,
                    "url": null
                  },
                  "t": {
                    "…": "…"
                  },
                  "tp": {
                    "…": "…"
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND — no such restaurant."
          }
        },
        "security": []
      }
    },
    "/public/v1/countries": {
      "get": {
        "operationId": "public-countries",
        "summary": "List countries",
        "description": "Every country with its localized name and calling prefix, sorted by name, for the phone field. Cached for a day (Cache-Control: public, max-age=86400).\n\nRate limit: 60/min per IP",
        "tags": [
          "Public booking API: Restaurant and countries"
        ],
        "parameters": [
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "en, nl, de, fr or es. Falls back to Accept-Language, then en.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "locale": "en",
                  "countries": [
                    {
                      "id": 150,
                      "name": "Netherlands",
                      "iso": "NL",
                      "prefix": 31
                    }
                  ]
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/calendar": {
      "get": {
        "operationId": "public-calendar",
        "summary": "Days of a month",
        "description": "Every day of the month as open, closed, full or unavailable (outside the booking window) for a party size.\n\nRate limit: 120/min per restaurant and IP",
        "tags": [
          "Public booking API: Availability"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "party_size",
            "in": "query",
            "required": true,
            "description": "Guests, 1 up to booking.max_party from GET /restaurants/{organization_guid} (never more than 20).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "month",
            "in": "query",
            "required": true,
            "description": "Y-m.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "month": "2026-10",
                  "days": {
                    "2026-10-16": "open",
                    "2026-10-17": "full",
                    "2026-10-18": "closed",
                    "…": "…"
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND (unknown restaurant) or UNAVAILABLE (the restaurant takes no online bookings)."
          },
          "422": {
            "description": "INVALID, with errors."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/times": {
      "get": {
        "operationId": "public-times",
        "summary": "Times on a day",
        "description": "The bookable times for a date and party size, each with the deposit or card guarantee that applies, plus the ticketed events that day (their times are not bookable as a normal table).\n\nRate limit: 120/min per restaurant and IP\n\ndeposit is {per_person, total} and guarantee {fee, total, basis (per_guest or per_booking), free_cancellation_hours} (amounts as money) or null. events[]: {id, name, url}. A date outside the booking window gives times: []. lang only affects the event names.",
        "tags": [
          "Public booking API: Availability"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "party_size",
            "in": "query",
            "required": true,
            "description": "Guests, 1 up to booking.max_party from GET /restaurants/{organization_guid} (never more than 20).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": true,
            "description": "Y-m-d.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "en, nl, de, fr or es. Falls back to Accept-Language, then the restaurant's language, then en.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "date": "2026-10-24",
                  "times": [
                    {
                      "time": "18:00",
                      "deposit": null,
                      "guarantee": null
                    },
                    {
                      "time": "19:00",
                      "deposit": null,
                      "guarantee": null
                    }
                  ],
                  "events": []
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND or UNAVAILABLE."
          },
          "422": {
            "description": "INVALID."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/reservations": {
      "post": {
        "operationId": "public-reservation-create",
        "summary": "Book a table",
        "description": "Without a deposit or guarantee the reservation is confirmed at once and the guest is emailed. With a deposit it is held for 30 minutes and payment_url points at the payment page; with a card guarantee next_step.type is guarantee and the URL is the card page. After paying, the payment provider sends the guest back through the API, which redirects (303) to your return_url, or without one to manage_url?paid=1. An Apple Pay or Google Pay deposit can be charged in this call (wallet_status).\n\nRate limit: 10/min per restaurant and IP\n\nThe manage_url is the guest's own page; its last path segment is the confirmation token used by the manage, guarantee and tickets endpoints.\n\nreservation.deposit is a formatted amount (e.g. \"€ 20,00\") or null. reservation.status is the stored status; state is pending, confirmed, cancelled or expired. payment_required stays true while a deposit or card is still due.",
        "tags": [
          "Public booking API: Reservations"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "request_id": {
                    "type": "string",
                    "description": "Your idempotency id, 8–64 letters, digits or dashes (a UUID works). Sending the same id again returns the first result with replayed: true."
                  },
                  "party_size": {
                    "type": "integer",
                    "description": "Number of guests: 1 up to booking.max_party (table bookings) or 1–20 (tickets)."
                  },
                  "date": {
                    "type": "string",
                    "description": "Y-m-d."
                  },
                  "time": {
                    "type": "string",
                    "description": "H:i, one of the times returned by the times endpoint."
                  },
                  "first_name": {
                    "type": "string",
                    "description": "Max 80 characters."
                  },
                  "last_name": {
                    "type": "string",
                    "description": "Max 80 characters."
                  },
                  "email": {
                    "type": "string",
                    "description": "An email address, max 190 characters."
                  },
                  "phone_country_id": {
                    "type": "integer",
                    "description": "A country id from GET /countries."
                  },
                  "phone": {
                    "type": "string",
                    "description": "6–25 characters: digits, spaces and + ( ) . -"
                  },
                  "note": {
                    "type": "string",
                    "description": "Max 500 characters."
                  },
                  "marketing_opt_in": {
                    "type": "boolean",
                    "description": "The guest agrees to receive marketing."
                  },
                  "source": {
                    "type": "string",
                    "description": "booking_page (default) or widget."
                  },
                  "lang": {
                    "type": "string",
                    "description": "en, nl, de, fr or es — the language of the emails."
                  },
                  "return_url": {
                    "type": "string",
                    "description": "http(s) URL, max 2000. Where the guest lands after paying; without it they land on the reservation page in the Conciar guest app."
                  },
                  "guarantee_consent": {
                    "type": "boolean",
                    "description": "Must be true when a card guarantee applies (show terms.consent_text from GET …/guarantee)."
                  },
                  "payment_method": {
                    "type": "object",
                    "description": "The deposit payment method the guest chose: payment_id (integer), payment_service_provider_id (integer) and payment_key (max 50), all required when payment_method is sent. Must be enabled for the restaurant."
                  },
                  "apple_pay_token, apple_pay_payment_data": {
                    "type": "object",
                    "description": "Required when payment_method.payment_key is applepay."
                  },
                  "payment_data": {
                    "type": "string",
                    "description": "The Google Pay token. Required when payment_method.payment_key is google_pay."
                  }
                },
                "required": [
                  "request_id",
                  "party_size",
                  "date",
                  "time",
                  "first_name",
                  "last_name",
                  "email",
                  "phone_country_id",
                  "phone"
                ]
              },
              "example": {
                "request_id": "6f1c2a9e-0000-4000-8000-000000000000",
                "party_size": 2,
                "date": "2026-10-24",
                "time": "19:00",
                "first_name": "Alex",
                "last_name": "Example",
                "email": "alex@example.com",
                "phone_country_id": 150,
                "phone": "+31 6 00000000",
                "return_url": "https://www.example.com/booked"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replay of an earlier request_id (replayed: true)."
          },
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "replayed": false,
                  "payment_required": false,
                  "payment_url": null,
                  "next_step": null,
                  "wallet_status": null,
                  "hold_minutes": 30,
                  "manage_url": "https://r.conciar.com/bistro-example/reservation/0000000000000000000000000000000000000000",
                  "reservation": {
                    "reference": "EXAMPLE-R-0001",
                    "date": "2026-10-24",
                    "time": "19:00",
                    "party_size": 2,
                    "name": "Alex Example",
                    "email": "alex@example.com",
                    "status": "confirmed",
                    "state": "confirmed",
                    "source": "booking_page",
                    "locale": "en",
                    "deposit": null,
                    "deposit_paid": false
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND (unknown restaurant) or UNAVAILABLE."
          },
          "409": {
            "description": "DEPOSIT_UNAVAILABLE or GUARANTEE_UNAVAILABLE — the restaurant cannot take the payment it requires."
          },
          "422": {
            "description": "INVALID (with errors; also a party_size above booking.max_party), TOO_SOON, TOO_FAR, SLOT_TAKEN, TICKETS_REQUIRED, CONSENT_REQUIRED or PAYMENT_METHOD_UNAVAILABLE."
          },
          "502": {
            "description": "PAYMENT_FAILED — the payment could not be started."
          },
          "503": {
            "description": "BUSY — try again."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/reservations/{request_id}": {
      "get": {
        "operationId": "public-reservation-status",
        "summary": "Get a booking by request id",
        "description": "Look up a booking you made with request_id, e.g. after the guest returns from paying.\n\nRate limit: 120/min per restaurant and IP\n\ntickets is {reference, quantity, event, total (formatted), status} or null; guarantee is {amount (formatted), deadline (localized text), status} or null, and stays null while the guarantee is pending or failed.",
        "tags": [
          "Public booking API: Reservations"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "request_id",
            "in": "path",
            "required": true,
            "description": "The request_id you booked with.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "payment_required": false,
                  "payment_url": null,
                  "next_step": null,
                  "manage_url": "https://r.conciar.com/bistro-example/reservation/0000000000000000000000000000000000000000",
                  "reservation": {
                    "reference": "EXAMPLE-R-0001",
                    "date": "2026-10-24",
                    "time": "19:00",
                    "party_size": 2,
                    "name": "Alex Example",
                    "email": "alex@example.com",
                    "status": "confirmed",
                    "state": "confirmed",
                    "source": "booking_page",
                    "locale": "en",
                    "deposit": null,
                    "deposit_paid": false
                  },
                  "tickets": null,
                  "guarantee": null
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND — unknown restaurant, or no booking (from the booking page or widget) with this request_id."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/guarantee": {
      "get": {
        "operationId": "public-guarantee-terms",
        "summary": "Card guarantee terms",
        "description": "Whether a no-show card guarantee applies to a date, time and party size, and its fee, deadline and the consent text to show the guest.\n\nRate limit: 120/min per restaurant and IP\n\nWhen a guarantee applies, terms is {fee, total (money), basis, free_cancellation_hours, deadline (Y-m-d H:i), deadline_label, total_label, consent_text}. reason (NO_MOLLIE or NO_CARD_METHOD) and message explain why it is unavailable.",
        "tags": [
          "Public booking API: Reservations"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "party_size",
            "in": "query",
            "required": true,
            "description": "1–20.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": true,
            "description": "Y-m-d.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "time",
            "in": "query",
            "required": true,
            "description": "H:i.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "en, nl, de, fr or es (anything else is 422 INVALID). Falls back to Accept-Language, then the restaurant's language, then en.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "required": false,
                  "available": true,
                  "reason": null,
                  "message": null,
                  "terms": null
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND — unknown restaurant, or not a restaurant."
          },
          "422": {
            "description": "INVALID, with errors."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/reservations/{token}/guarantee": {
      "get": {
        "operationId": "public-reservation-guarantee",
        "summary": "A booking's card guarantee",
        "description": "Rate limit: 120/min per restaurant and IP\n\nWith a guarantee: guarantee_status (pending, active, failed, charging, charge_failed, charged, waived), awaits_card, card_on_file, terms ({amount, deadline, status} or null), deadline (Y-m-d H:i), deadline_passed and payment_url while a card is still needed. Unlike the manage calls, the token does not expire here.",
        "tags": [
          "Public booking API: Reservations"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The 40-character confirmation token from manage_url (letters and digits).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "has_guarantee": false
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND — unknown restaurant or token."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/reservations/{token}/guarantee/card": {
      "post": {
        "operationId": "public-reservation-guarantee-card",
        "summary": "Get the card page",
        "description": "The page where the guest registers the card for the guarantee.\n\nRate limit: 10/min per restaurant and IP",
        "tags": [
          "Public booking API: Reservations"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The 40-character confirmation token from manage_url (letters and digits).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "payment_url": "https://payment-provider.example/card/…"
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND — unknown restaurant or token."
          },
          "409": {
            "description": "NO_CARD_DUE — no card is needed, or a card payment could not be started."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/reservations/{token}/manage": {
      "get": {
        "operationId": "public-manage-show",
        "summary": "Get the reservation",
        "description": "Rate limit: 120/min per restaurant and IP\n\nstate is confirmed, pending, cancelled or past. deposit is a formatted amount or null; guarantee is {amount, deadline, status, deadline_passed} or null; tickets is {reference, quantity, event, total, status} or null. sms.available is true only for an upcoming reservation, at a restaurant that sends texts, for a guest with a mobile number.",
        "tags": [
          "Public booking API: The guest's reservation"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The confirmation token from manage_url (40 letters and digits; the route accepts 32–64).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "en, nl, de, fr or es. Otherwise the language the guest booked in.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "locale": "en",
                  "handle": "bistro-example",
                  "reservation": {
                    "reference": "EXAMPLE-R-0001",
                    "date": "2026-10-24",
                    "time": "19:00",
                    "party_size": 2,
                    "name": "Alex Example",
                    "email": "alex@example.com",
                    "note": null
                  },
                  "state": "confirmed",
                  "expired": false,
                  "deposit": null,
                  "deposit_paid": false,
                  "payment_url": null,
                  "awaits_card": false,
                  "guarantee": null,
                  "tickets": null,
                  "can_cancel": true,
                  "address": "Example Street 1, 1000 AA Example City",
                  "sms": {
                    "available": true,
                    "opted_out": false
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/reservations/{token}/cancel": {
      "post": {
        "operationId": "public-manage-cancel",
        "summary": "Cancel the reservation",
        "description": "The guest is emailed and the restaurant notified. Returns the same fields as the manage call plus outcome: cancelled or already (200), or not_cancellable.\n\nRate limit: 10/min per restaurant and IP",
        "tags": [
          "Public booking API: The guest's reservation"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The confirmation token from manage_url (40 letters and digits; the route accepts 32–64).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "outcome": "cancelled",
                  "state": "cancelled",
                  "can_cancel": false,
                  "…": "…"
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND."
          },
          "422": {
            "description": "{status: false, outcome: not_cancellable, …} — not confirmed or pending, in the past, or has paid tickets."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/reservations/{token}/sms-stop": {
      "post": {
        "operationId": "public-manage-sms-stop",
        "summary": "Stop text messages",
        "description": "Rate limit: 10/min per restaurant and IP",
        "tags": [
          "Public booking API: The guest's reservation"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The confirmation token from manage_url (40 letters and digits; the route accepts 32–64).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "sms": {
                    "available": true,
                    "opted_out": true
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND."
          },
          "422": {
            "description": "{status: false, sms} (no code) — the guest has no valid mobile number."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/reservations/{token}/sms-start": {
      "post": {
        "operationId": "public-manage-sms-start",
        "summary": "Resume text messages",
        "description": "Rate limit: 10/min per restaurant and IP",
        "tags": [
          "Public booking API: The guest's reservation"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The confirmation token from manage_url (40 letters and digits; the route accepts 32–64).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "sms": {
                    "available": true,
                    "opted_out": false
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND."
          },
          "422": {
            "description": "{status: false, sms} (no code) — the guest has no valid mobile number."
          }
        },
        "security": []
      }
    },
    "/public/v1/short/{code}": {
      "get": {
        "operationId": "public-short-link",
        "summary": "Resolve a text-message short code",
        "description": "The 8-character code in a reservation text message to the reservation page.\n\nRate limit: 30/min per IP",
        "tags": [
          "Public booking API: The guest's reservation"
        ],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "description": "8 characters: uppercase letters and the digits 2–9 (no I, L, O, 0 or 1).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "handle": "bistro-example",
                  "token": "0000000000000000000000000000000000000000",
                  "url": "https://r.conciar.com/bistro-example/reservation/0000000000000000000000000000000000000000"
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND — unknown or expired."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/events": {
      "get": {
        "operationId": "public-events-list",
        "summary": "List events",
        "description": "Ticketed events that are on sale or not on sale yet.\n\nRate limit: 120/min per restaurant and IP\n\nseating is tables or seats; state is not_ticketed, not_started, open or ended; sale_opens is a date text or null; start_time and end_time are null (and start_iso a date) for all-day events.",
        "tags": [
          "Public booking API: Ticketed events"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "en, nl, de, fr or es. Falls back to Accept-Language, then the restaurant's language, then en.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "events": [
                    {
                      "id": 7,
                      "name": "Example wine dinner",
                      "description": "Five courses with matching wines.",
                      "url": "https://r.conciar.com/bistro-example/events/7-example-wine-dinner?lang=en",
                      "slug": "example-wine-dinner",
                      "when": "Friday 30 October 2026 · 19:00–23:00",
                      "start_date": "2026-10-30",
                      "end_date": "2026-10-30",
                      "start_time": "19:00",
                      "end_time": "23:00",
                      "start_iso": "2026-10-30T19:00",
                      "seating": "tables",
                      "unit": {
                        "amount": "65.00",
                        "minor": 6500,
                        "currency": "EUR"
                      },
                      "unit_label": "€65.00",
                      "vat_rate": 9,
                      "max_per_booking": 8,
                      "state": "open",
                      "remaining": 24,
                      "sold_out": false,
                      "sale_opens": null
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND — unknown restaurant, or not a restaurant."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/events/{event}": {
      "get": {
        "operationId": "public-event-show",
        "summary": "Get an event",
        "description": "Rate limit: 120/min per restaurant and IP\n\nEnded events are still returned; on_sale is true only while the sale is open and tickets remain.",
        "tags": [
          "Public booking API: Ticketed events"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "Event id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "en, nl, de, fr or es. Falls back to Accept-Language, then the restaurant's language, then en.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "event": {
                    "id": 7,
                    "name": "Example wine dinner",
                    "description": "Five courses with matching wines.",
                    "url": "https://r.conciar.com/bistro-example/events/7-example-wine-dinner?lang=en",
                    "slug": "example-wine-dinner",
                    "when": "Friday 30 October 2026 · 19:00–23:00",
                    "start_date": "2026-10-30",
                    "end_date": "2026-10-30",
                    "start_time": "19:00",
                    "end_time": "23:00",
                    "start_iso": "2026-10-30T19:00",
                    "seating": "tables",
                    "unit": {
                      "amount": "65.00",
                      "minor": 6500,
                      "currency": "EUR"
                    },
                    "unit_label": "€65.00",
                    "vat_rate": 9,
                    "max_per_booking": 8,
                    "state": "open",
                    "remaining": 24,
                    "sold_out": false,
                    "sale_opens": null
                  },
                  "on_sale": true,
                  "max_tickets": 8,
                  "hold_minutes": 30,
                  "t": {
                    "…": "…"
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND — unknown restaurant, or no published ticketed event with this id."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/events/{event}/dates": {
      "get": {
        "operationId": "public-event-dates",
        "summary": "Event dates",
        "description": "Rate limit: 120/min per restaurant and IP\n\nstatus is open or full.",
        "tags": [
          "Public booking API: Ticketed events"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "Event id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "party_size",
            "in": "query",
            "required": true,
            "description": "1–20.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "dates": [
                    {
                      "date": "2026-10-30",
                      "status": "open"
                    }
                  ]
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND."
          },
          "422": {
            "description": "INVALID."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/events/{event}/times": {
      "get": {
        "operationId": "public-event-times",
        "summary": "Event times and price",
        "description": "Rate limit: 120/min per restaurant and IP\n\ntimes is [] when fewer tickets remain than party_size.",
        "tags": [
          "Public booking API: Ticketed events"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "Event id.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "party_size",
            "in": "query",
            "required": true,
            "description": "1–20.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": true,
            "description": "Y-m-d.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "date": "2026-10-30",
                  "times": [
                    "19:00"
                  ],
                  "total": {
                    "amount": "130.00",
                    "minor": 13000,
                    "currency": "EUR"
                  },
                  "tax": {
                    "amount": "10.73",
                    "minor": 1073,
                    "currency": "EUR"
                  },
                  "vat_rate": 9
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND."
          },
          "422": {
            "description": "INVALID."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/events/{event}/tickets": {
      "post": {
        "operationId": "public-event-tickets",
        "summary": "Buy tickets",
        "description": "Books the tickets and returns the payment page; the booking is held for 30 minutes until paid. After paying, the guest lands on your return_url (through an API redirect), or without one on the reservation page.\n\nRate limit: 10/min per restaurant and IP",
        "tags": [
          "Public booking API: Ticketed events"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event",
            "in": "path",
            "required": true,
            "description": "Event id.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "request_id": {
                    "type": "string",
                    "description": "Your idempotency id, 8–64 letters, digits or dashes (a UUID works). Sending the same id again returns the first result with replayed: true."
                  },
                  "party_size": {
                    "type": "integer",
                    "description": "Number of guests: 1 up to booking.max_party (table bookings) or 1–20 (tickets)."
                  },
                  "date": {
                    "type": "string",
                    "description": "Y-m-d."
                  },
                  "time": {
                    "type": "string",
                    "description": "H:i, one of the times returned by the times endpoint."
                  },
                  "first_name": {
                    "type": "string",
                    "description": "Max 80 characters."
                  },
                  "last_name": {
                    "type": "string",
                    "description": "Max 80 characters."
                  },
                  "email": {
                    "type": "string",
                    "description": "An email address, max 190 characters."
                  },
                  "phone_country_id": {
                    "type": "integer",
                    "description": "A country id from GET /countries."
                  },
                  "phone": {
                    "type": "string",
                    "description": "6–25 characters: digits, spaces and + ( ) . -"
                  },
                  "note": {
                    "type": "string",
                    "description": "Max 500 characters."
                  },
                  "marketing_opt_in": {
                    "type": "boolean",
                    "description": "The guest agrees to receive marketing."
                  },
                  "source": {
                    "type": "string",
                    "description": "booking_page (default) or widget."
                  },
                  "lang": {
                    "type": "string",
                    "description": "en, nl, de, fr or es — the language of the emails."
                  },
                  "return_url": {
                    "type": "string",
                    "description": "http(s) URL, max 2000. Where the guest lands after paying; without it they land on the reservation page in the Conciar guest app."
                  }
                },
                "required": [
                  "request_id",
                  "party_size",
                  "date",
                  "time",
                  "first_name",
                  "last_name",
                  "email",
                  "phone_country_id",
                  "phone"
                ]
              },
              "example": {
                "request_id": "0b7d4c1e-0000-4000-8000-000000000000",
                "party_size": 2,
                "date": "2026-10-30",
                "time": "19:00",
                "first_name": "Alex",
                "last_name": "Example",
                "email": "alex@example.com",
                "phone_country_id": 150,
                "phone": "+31 6 00000000"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replay of an earlier request_id (replayed: true)."
          },
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "replayed": false,
                  "payment_url": "https://payment-provider.example/checkout/…",
                  "hold_minutes": 30,
                  "manage_url": "https://r.conciar.com/bistro-example/reservation/0000000000000000000000000000000000000000",
                  "token": "0000000000000000000000000000000000000000",
                  "tickets": {
                    "reference": "EXAMPLE-T-0001",
                    "quantity": 2,
                    "date": "2026-10-30",
                    "time": "19:00",
                    "status": "pending"
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND."
          },
          "409": {
            "description": "TICKETS_UNAVAILABLE, SALE_CLOSED or SOLD_OUT (with message)."
          },
          "422": {
            "description": "INVALID, TOO_MANY (more than the event allows per booking) or SLOT_TAKEN."
          },
          "502": {
            "description": "PAYMENT_FAILED."
          },
          "503": {
            "description": "BUSY."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/reservations/{token}/tickets": {
      "get": {
        "operationId": "public-reservation-tickets",
        "summary": "A booking's tickets",
        "description": "Rate limit: 120/min per restaurant and IP\n\ntickets.status is pending, paid, cancelled or refunded; payment_url is set only while pending. The token does not expire here.",
        "tags": [
          "Public booking API: Ticketed events"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its handle (any case, a leading @ is ignored; former handles still resolve).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The 40-character confirmation token from manage_url (letters and digits).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "tickets": {
                    "reference": "EXAMPLE-T-0001",
                    "quantity": 2,
                    "event": "Example wine dinner",
                    "total": "€ 130,00",
                    "status": "paid"
                  },
                  "payment_url": null
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/gift-cards": {
      "get": {
        "operationId": "public-gift-cards-show",
        "summary": "Gift card settings",
        "description": "Whether gift cards are on sale (reason when not: NO_RESTAURANT, DISABLED or NO_ONLINE_PAYMENTS), the preset amounts, the custom amount range and how long cards stay valid.\n\nRate limit: 60/min per restaurant and IP\n\nA restaurant that does not sell gift cards online still answers 200, with available: false, the reason and presets: [].",
        "tags": [
          "Public booking API: Gift cards"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its current handle, matched exactly (no @, no former handles).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "en, nl, de, fr or es. Falls back to Accept-Language, then the restaurant's language, then en.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "available": true,
                  "reason": null,
                  "locale": "en",
                  "locales": [
                    "en",
                    "nl",
                    "de",
                    "fr",
                    "es"
                  ],
                  "restaurant": {
                    "name": "Bistro Example",
                    "guid": "00000000000000000",
                    "handle": "bistro-example",
                    "logo": null,
                    "accent": "#1f6f5c",
                    "email": "hello@example.com",
                    "website": null
                  },
                  "page_url": "https://r.conciar.com/bistro-example/gift-card",
                  "currency": "EUR",
                  "presets": [
                    {
                      "amount": "25.00",
                      "minor": 2500,
                      "currency": "EUR"
                    },
                    {
                      "amount": "50.00",
                      "minor": 5000,
                      "currency": "EUR"
                    }
                  ],
                  "allow_custom_amount": true,
                  "min_amount": {
                    "amount": "10.00",
                    "minor": 1000,
                    "currency": "EUR"
                  },
                  "max_amount": {
                    "amount": "500.00",
                    "minor": 50000,
                    "currency": "EUR"
                  },
                  "validity_months": 24,
                  "validity_text": "…"
                }
              }
            }
          },
          "404": {
            "description": "Unknown restaurant (plain {message})."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/gift-cards/purchase": {
      "post": {
        "operationId": "public-gift-card-purchase",
        "summary": "Buy a gift card",
        "description": "Returns the payment page. After paying, the buyer lands on status_url in the Conciar guest app; the card is emailed to the buyer or the recipient.\n\nRate limit: 6/min per restaurant and IP",
        "tags": [
          "Public booking API: Gift cards"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its current handle, matched exactly (no @, no former handles).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "request_id": {
                    "type": "string",
                    "description": "Your idempotency id, 8–64 letters, digits or dashes."
                  },
                  "amount": {
                    "type": "number",
                    "description": "1–100000; a preset, or within the custom range when allowed."
                  },
                  "purchaser_name": {
                    "type": "string",
                    "description": "Max 160."
                  },
                  "purchaser_email": {
                    "type": "string",
                    "description": "Max 190."
                  },
                  "deliver_to": {
                    "type": "string",
                    "description": "recipient or buyer."
                  },
                  "recipient_name": {
                    "type": "string",
                    "description": "Max 160."
                  },
                  "recipient_email": {
                    "type": "string",
                    "description": "An email address, max 190. Required when deliver_to is recipient."
                  },
                  "message": {
                    "type": "string",
                    "description": "Max 500."
                  },
                  "marketing_opt_in": {
                    "type": "boolean",
                    "description": "Consent to marketing."
                  },
                  "lang": {
                    "type": "string",
                    "description": "en, nl, de, fr or es."
                  }
                },
                "required": [
                  "request_id",
                  "amount",
                  "purchaser_name",
                  "purchaser_email",
                  "deliver_to"
                ]
              },
              "example": {
                "request_id": "3a9e5f20-0000-4000-8000-000000000000",
                "amount": 50,
                "purchaser_name": "Alex Example",
                "purchaser_email": "alex@example.com",
                "deliver_to": "buyer"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "replayed": false,
                  "payment_url": "https://payment-provider.example/checkout/…",
                  "token": "ExampleGiftCardToken0000000000000000000000000000",
                  "status_url": "https://r.conciar.com/bistro-example/gift-card/order/ExampleGiftCardToken0000000000000000000000000000"
                }
              }
            }
          },
          "404": {
            "description": "UNAVAILABLE — unknown restaurant, or it does not sell gift cards online."
          },
          "409": {
            "description": "UNAVAILABLE — online payments are not available."
          },
          "422": {
            "description": "INVALID (with errors) or INVALID_AMOUNT."
          },
          "502": {
            "description": "PAYMENT_FAILED."
          },
          "503": {
            "description": "BUSY."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/gift-cards/purchase/{token}": {
      "get": {
        "operationId": "public-gift-card-order",
        "summary": "Purchase status",
        "description": "paid, pending or failed (a payment still pending after two hours counts as failed). card_url when paid, payment_url while pending.\n\nRate limit: 60/min per restaurant and IP",
        "tags": [
          "Public booking API: Gift cards"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its current handle, matched exactly (no @, no former handles).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The 48-character token from the purchase (32–64 accepted).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "state": "paid",
                  "locale": "en",
                  "restaurant": {
                    "…": "…"
                  },
                  "amount": {
                    "amount": "50.00",
                    "minor": 5000,
                    "currency": "EUR"
                  },
                  "to_recipient": false,
                  "sent_to": "alex@example.com",
                  "card_url": "https://r.conciar.com/bistro-example/gift-card/card/ExampleGiftCardToken0000000000000000000000000000?sig=…",
                  "payment_url": null,
                  "page_url": "https://r.conciar.com/bistro-example/gift-card"
                }
              }
            }
          },
          "404": {
            "description": "Unknown restaurant or token (plain {message})."
          }
        },
        "security": []
      }
    },
    "/public/v1/restaurants/{organization_guid}/gift-cards/card/{token}": {
      "get": {
        "operationId": "public-gift-card-card",
        "summary": "Get the gift card",
        "description": "The paid card itself, for the printable card page: its code, amount, balance and expiry. Needs the signature from card_url. The answer contains the card's redeemable code.\n\nRate limit: 60/min per restaurant and IP\n\ngift_card.status is active, redeemed, expired or void.",
        "tags": [
          "Public booking API: Gift cards"
        ],
        "parameters": [
          {
            "name": "organization_guid",
            "in": "path",
            "required": true,
            "description": "The restaurant's guid or its current handle, matched exactly (no @, no former handles).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "description": "The 48-character token from the purchase or card_url (32–64 accepted).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sig",
            "in": "query",
            "required": true,
            "description": "The signature from card_url. It does not expire.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lang",
            "in": "query",
            "required": false,
            "description": "en, nl, de, fr or es: show the card in that language. Otherwise the card's own language.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "example": {
                  "status": true,
                  "locale": "en",
                  "restaurant": {
                    "name": "Bistro Example",
                    "guid": "00000000000000000",
                    "handle": "bistro-example",
                    "logo": null,
                    "accent": "#1f6f5c",
                    "email": "hello@example.com",
                    "website": null
                  },
                  "gift_card": {
                    "code": "…",
                    "status": "active",
                    "amount": {
                      "amount": "50.00",
                      "minor": 5000,
                      "currency": "EUR"
                    },
                    "balance": {
                      "amount": "50.00",
                      "minor": 5000,
                      "currency": "EUR"
                    },
                    "amount_text": "€50.00",
                    "balance_text": "€50.00",
                    "expires_at": "2028-10-28",
                    "expires_text": "28 October 2028",
                    "recipient_name": null,
                    "purchaser_name": "Alex Example",
                    "message": null
                  },
                  "t": {
                    "…": "…"
                  }
                }
              }
            }
          },
          "403": {
            "description": "INVALID_LINK — missing or wrong sig, or the card is not paid yet."
          },
          "404": {
            "description": "Unknown restaurant or token (plain {message})."
          }
        },
        "security": []
      }
    }
  }
}