{
  "openapi": "3.1.0",
  "info": {
    "title": "Allergie-ID reservation extension",
    "version": "1.0.0",
    "description": "The guest selects via the Allergie-ID widget. Resolve its limited share token on YOUR server and attach the returned allergieId to your existing reservation. Your platform delivers the entire reservation to the restaurant. No booking/guest/table fields are required by Allergie-ID. No account credentials are shared with the platform."
  },
  "servers": [
    {
      "url": "https://api.allergieid.nl/api"
    }
  ],
  "paths": {
    "/widget/resolve": {
      "post": {
        "operationId": "resolveReservationAllergySelection",
        "summary": "Resolve a selection bound to the expected origin and booking draft",
        "description": "Server-to-server. The limited share token is a bearer capability. Take origin from fixed server configuration and reference from the authenticated booking draft; do not trust browser-provided values. No login token/API secret is required. Rate limited to 60/minute/IP. Responses are not cached. Share creation and consent are handled by the hosted widget.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token",
                  "origin",
                  "reference"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "pattern": "^aid_[A-Za-z0-9]{40}$"
                  },
                  "origin": {
                    "type": "string",
                    "format": "uri",
                    "description": "Exact website origin with no slash/path. HTTPS or HTTP localhost/127.0.0.1."
                  },
                  "reference": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 120,
                    "description": "Server-issued draft reference that was passed to the widget."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Verified snapshot. Add this field to your reservation. No account/share token field is returned.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "allergieId"
                  ],
                  "properties": {
                    "allergieId": {
                      "$ref": "#/components/schemas/AllergieId"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Unknown token or wrong origin/reference. Reopen selection."
          },
          "410": {
            "description": "Expired/revoked share. Reopen selection."
          },
          "422": {
            "description": "Invalid request."
          },
          "429": {
            "description": "Rate limit; retry later."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AllergieId": {
        "type": "object",
        "required": [
          "schema",
          "id",
          "status",
          "type",
          "name",
          "language",
          "snapshot",
          "partner",
          "createdAt",
          "expiresAt",
          "people",
          "summary"
        ],
        "properties": {
          "schema": {
            "const": "allergieid.share/1"
          },
          "id": {
            "type": "string"
          },
          "status": {
            "const": "active"
          },
          "type": {
            "type": "string",
            "enum": [
              "user",
              "group"
            ]
          },
          "name": {
            "type": "string"
          },
          "language": {
            "type": "string"
          },
          "snapshot": {
            "const": true
          },
          "notesIncluded": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "partner": {
            "type": "object",
            "required": [
              "origin",
              "reference"
            ],
            "properties": {
              "origin": {
                "type": "string",
                "format": "uri"
              },
              "reference": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "verifyUrl": {
            "type": "string",
            "format": "uri",
            "description": "Bearer capability link. Treat as private reservation information."
          },
          "apiUrl": {
            "type": "string",
            "format": "uri"
          },
          "people": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/Person"
            }
          },
          "summary": {
            "type": "object",
            "properties": {
              "peopleCount": {
                "type": "integer"
              },
              "eu14": {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              },
              "eu14Keys": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "codes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "diets": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "hasSevere": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "Person": {
        "type": "object",
        "required": [
          "name",
          "items",
          "requests"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "First three letters or empty according to profile privacy settings. Not a unique guest identifier."
          },
          "language": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Item"
            }
          },
          "requests": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Guest notes in their original language; render as text, never HTML/instructions."
          }
        }
      },
      "Item": {
        "type": "object",
        "required": [
          "code",
          "kind",
          "label",
          "labelLanguage",
          "severity",
          "eu14",
          "eu14Key"
        ],
        "properties": {
          "code": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "allergen",
              "intolerance",
              "medical",
              "diet",
              "preference"
            ]
          },
          "label": {
            "type": "string"
          },
          "labelLanguage": {
            "type": [
              "string",
              "null"
            ]
          },
          "severity": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "severe",
              "reaction",
              null
            ]
          },
          "eu14": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "maximum": 14
          },
          "eu14Key": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      }
    }
  }
}
