{
  "openapi": "3.1.0",
  "info": {
    "title": "vFound API",
    "version": "1.0.0",
    "summary": "Lost & Found, Parcels, Checkroom, Equipment and Visitors for front desks.",
    "description": "Every plan includes the API. Create a key in Settings, For developers, choose its scopes, and send it as a Bearer token. Each operation names the scope it needs. Changes accept an Idempotency-Key header for safe retries. The reference with examples is at https://vfound.io/developers. A key may name the team member it acts for in an X-Acting-User header; history and audit then name that person.",
    "termsOfService": "https://vfound.io/terms",
    "contact": {
      "name": "vFound",
      "url": "https://vfound.io/developers",
      "email": "armaan@vfound.io"
    }
  },
  "servers": [
    {
      "url": "https://vfound.io/api/v1"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Lost & Found"
    },
    {
      "name": "Parcels"
    },
    {
      "name": "Checkroom"
    },
    {
      "name": "Equipment"
    },
    {
      "name": "Visitors"
    },
    {
      "name": "People"
    },
    {
      "name": "Webhooks"
    },
    {
      "name": "Stays",
      "description": "Minimal private hotel stay context for Lost & Found and Parcels. Room search never suggests ownership."
    }
  ],
  "paths": {
    "/items": {
      "get": {
        "operationId": "listItems",
        "summary": "List found items",
        "tags": [
          "Lost & Found"
        ],
        "security": [
          {
            "apiKey": [
              "items:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "in_care",
                "in_transit",
                "claimed",
                "expired",
                "donated",
                "disposed",
                "trash",
                "pending_witness"
              ]
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "description": "Only records changed at or after this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Words in the title, description, brand, colour or tags.",
            "schema": {
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "context",
            "in": "query",
            "style": "deepObject",
            "explode": true,
            "description": "Up to five exact private context field filters, ANDed. Does not widen venue scope.",
            "schema": {
              "type": "object",
              "maxProperties": 5,
              "additionalProperties": {
                "type": "string",
                "maxLength": 100
              }
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Item"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createItem",
        "summary": "Add a found item",
        "tags": [
          "Lost & Found"
        ],
        "security": [
          {
            "apiKey": [
              "items:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "category": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer"
                      }
                    ],
                    "description": "A name from GET /categories, or its id."
                  },
                  "found_date": {
                    "type": "string",
                    "format": "date"
                  },
                  "found_time": {
                    "type": "string",
                    "description": "HH:MM"
                  },
                  "keep_until": {
                    "type": "string",
                    "format": "date"
                  },
                  "location": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "colour": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "brand": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "tags": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ],
                    "description": "Comma-separated, or a list."
                  },
                  "value_band": {
                    "type": "string",
                    "enum": [
                      "unknown",
                      "low",
                      "medium",
                      "high"
                    ]
                  },
                  "notes": {
                    "type": "string",
                    "description": "Staff only.",
                    "maxLength": 10000
                  },
                  "photo_public": {
                    "type": "boolean"
                  },
                  "photo": {
                    "type": "string",
                    "description": "A base64 data URL up to 8 MB. Not checked by vFound AI's privacy guard: set photo_public to false for any photo showing personal details."
                  },
                  "stay_id": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "A stay id from GET /stays at this venue."
                  },
                  "room_at_event": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 60,
                    "description": "Room at the moment this record was logged. Defaults to the stay current room and does not change on a later room move."
                  },
                  "custom_values": {
                    "type": "object",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean",
                        "null"
                      ]
                    },
                    "description": "vFound Enterprise custom attributes, by field key (see the fields in Settings, Custom attributes). Unknown keys, values of the wrong type and choices outside the field's options are refused with 422. Send null or an empty string to clear a value. Required fields are enforced on the workspace forms, never on the API. After the plan ends new values are refused with 422; stored values stay."
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  },
                  "journey": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "maxProperties": 8,
                    "additionalProperties": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "maxLength": 100
                    },
                    "description": "Private context in the named versioned schema. Null historical schema means legacy-v1. service_at requires an ISO instant with an offset. Unknown keys and non-string values are rejected."
                  },
                  "journey_schema": {
                    "type": "string",
                    "maxLength": 40
                  }
                },
                "required": [
                  "title",
                  "category"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Item"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/items/{id}": {
      "get": {
        "operationId": "getItem",
        "summary": "Get a found item",
        "tags": [
          "Lost & Found"
        ],
        "security": [
          {
            "apiKey": [
              "items:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Item"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateItem",
        "summary": "Update a found item",
        "tags": [
          "Lost & Found"
        ],
        "security": [
          {
            "apiKey": [
              "items:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "category": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "integer"
                      }
                    ],
                    "description": "A name from GET /categories, or its id."
                  },
                  "location": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "colour": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "brand": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "tags": {
                    "oneOf": [
                      {
                        "type": "string"
                      },
                      {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    ],
                    "description": "Comma-separated, or a list."
                  },
                  "value_band": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "unknown",
                      "low",
                      "medium",
                      "high",
                      null
                    ]
                  },
                  "notes": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "photo_public": {
                    "type": "boolean"
                  },
                  "keep_until": {
                    "type": "string",
                    "format": "date"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "in_care",
                      "expired",
                      "donated",
                      "disposed",
                      "trash"
                    ]
                  },
                  "stay_id": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "A stay id from GET /stays at this venue."
                  },
                  "room_at_event": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 60,
                    "description": "Room at the moment this record was logged. Defaults to the stay current room and does not change on a later room move."
                  },
                  "custom_values": {
                    "type": "object",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean",
                        "null"
                      ]
                    },
                    "description": "vFound Enterprise custom attributes, by field key (see the fields in Settings, Custom attributes). Unknown keys, values of the wrong type and choices outside the field's options are refused with 422. Send null or an empty string to clear a value. Required fields are enforced on the workspace forms, never on the API. After the plan ends new values are refused with 422; stored values stay."
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  },
                  "journey": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "maxProperties": 8,
                    "additionalProperties": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "maxLength": 100
                    },
                    "description": "Private context in the named versioned schema. Null historical schema means legacy-v1. service_at requires an ISO instant with an offset. Unknown keys and non-string values are rejected."
                  },
                  "journey_schema": {
                    "type": "string",
                    "maxLength": 40
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Item"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/item-transfers": {
      "get": {
        "operationId": "listItemTransfers",
        "summary": "List found items moving between venues",
        "tags": [
          "Lost & Found"
        ],
        "description": "Transfers this venue sent or receives, items still on their way first (up to 200). destinations lists the venues an owner or manager can send to; bins lists this venue's storage bins for receiving.",
        "security": [
          {
            "apiKey": [
              "items:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "in_transit",
                "received",
                "cancelled"
              ]
            }
          },
          {
            "name": "direction",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "incoming",
                "outgoing"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "destinations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "code"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "bins": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "code": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "id",
                          "code",
                          "name"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ItemTransfer"
                      }
                    }
                  },
                  "required": [
                    "destinations",
                    "bins",
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "sendItem",
        "summary": "Send a found item to another venue of the group",
        "tags": [
          "Lost & Found"
        ],
        "description": "An owner or manager sends an item waiting for its owner to another active venue of the same customer group that has Lost & Found. The item leaves the guest page and cannot change until it is received or the transfer is cancelled. Refused for an item with any claim, past its holding date, or not waiting for its owner.",
        "security": [
          {
            "apiKey": [
              "items:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "item_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "destination_business_id": {
                    "type": "integer",
                    "description": "A venue id from destinations in GET /item-transfers."
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "required": [
                  "item_id",
                  "destination_business_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ItemTransfer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/item-transfers/{id}/cancel": {
      "post": {
        "operationId": "cancelItemTransfer",
        "summary": "Cancel a found item transfer before it is received",
        "tags": [
          "Lost & Found"
        ],
        "description": "The sending venue's owner or manager takes the item back: it returns to its storage place and, unless its holding date passed, to the guest page.",
        "security": [
          {
            "apiKey": [
              "items:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ItemTransfer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/item-transfers/{id}/receive": {
      "post": {
        "operationId": "receiveItemTransfer",
        "summary": "Receive a found item from another venue",
        "tags": [
          "Lost & Found"
        ],
        "description": "The receiving venue confirms the item arrived. It then belongs to this venue with its photos, history, found date and holding date, goes into the chosen storage bin (required when the venue has bins), and is matched against this venue's open lost reports and alerts like a newly logged item.",
        "security": [
          {
            "apiKey": [
              "items:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "bin_id": {
                    "type": "integer",
                    "description": "A bin id from bins in GET /item-transfers."
                  },
                  "location": {
                    "type": "string",
                    "maxLength": 191,
                    "description": "Where it is kept, for a venue without storage bins."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ItemTransfer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/categories": {
      "get": {
        "operationId": "listCategories",
        "summary": "List item categories",
        "tags": [
          "Lost & Found"
        ],
        "security": [
          {
            "apiKey": [
              "items:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/claims": {
      "get": {
        "operationId": "listClaims",
        "summary": "List claims",
        "tags": [
          "Lost & Found"
        ],
        "security": [
          {
            "apiKey": [
              "claims:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "unread",
                "open",
                "accepted",
                "awaiting_information",
                "ready_for_pickup",
                "ready_for_shipment",
                "shipped",
                "closed",
                "rejected",
                "expired"
              ]
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "description": "Only records changed at or after this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Claim"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/claims/{id}": {
      "get": {
        "operationId": "getClaim",
        "summary": "Get a claim",
        "tags": [
          "Lost & Found"
        ],
        "security": [
          {
            "apiKey": [
              "claims:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The claim's reference."
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Claim"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/lost-reports": {
      "get": {
        "operationId": "listLostReports",
        "summary": "List lost reports",
        "tags": [
          "Lost & Found"
        ],
        "security": [
          {
            "apiKey": [
              "lost_reports:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "closed"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "context",
            "in": "query",
            "style": "deepObject",
            "explode": true,
            "description": "Up to five exact private context field filters, ANDed. Does not widen venue scope.",
            "schema": {
              "type": "object",
              "maxProperties": 5,
              "additionalProperties": {
                "type": "string",
                "maxLength": 100
              }
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LostReport"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "description": "Private paginated export includes current journey context and retained journey versions. Fetch every page; status is optional. Requires lost_reports:read for this venue. This endpoint is unavailable after account closure; download unlinked reports before closing. Linked reports and retained journeys remain in the existing claims CSV during its closure download window."
      },
      "post": {
        "operationId": "createLostReport",
        "summary": "Create a lost report for a guest",
        "tags": [
          "Lost & Found"
        ],
        "description": "Contact-centre intake. Sends the normal confirmation and private link in the selected language, not phone consent. Existing report limits, watch, matching and email rules apply; initial matching may use venue-enabled AI. Category is an existing numeric category id. No document or photo upload is accepted here. Authenticated assisted intake may supply contact_method email, phone or none, assistance_method phone or in_person and privacy_explained=true. Name may be omitted in this mode; guest reporting still requires email and name.",
        "security": [
          {
            "apiKey": [
              "lost_reports:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LostReport"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "first_name": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "last_name": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 191
                  },
                  "title": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "colour_brand": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "place_lost": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "phone": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 50
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "category": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "date_lost": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date"
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "es",
                      "fr",
                      "de",
                      "nl",
                      "it",
                      "pt",
                      "pl",
                      "sv",
                      "tr",
                      "ja",
                      "zh",
                      "ar"
                    ]
                  },
                  "journey": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "maxProperties": 8,
                    "additionalProperties": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "maxLength": 100
                    },
                    "description": "Private context in the named versioned schema. Null historical schema means legacy-v1. service_at requires an ISO instant with an offset. Unknown keys and non-string values are rejected."
                  },
                  "journey_schema": {
                    "type": "string",
                    "maxLength": 40
                  },
                  "contact_method": {
                    "type": "string",
                    "enum": [
                      "email",
                      "phone",
                      "none"
                    ]
                  },
                  "privacy_explained": {
                    "type": "boolean",
                    "const": true
                  },
                  "assistance_method": {
                    "type": "string",
                    "enum": [
                      "phone",
                      "in_person"
                    ]
                  }
                },
                "additionalProperties": false,
                "oneOf": [
                  {
                    "required": [
                      "first_name",
                      "last_name",
                      "email",
                      "title",
                      "description"
                    ],
                    "not": {
                      "required": [
                        "contact_method"
                      ]
                    }
                  },
                  {
                    "required": [
                      "contact_method",
                      "privacy_explained",
                      "assistance_method",
                      "title",
                      "description"
                    ]
                  }
                ]
              }
            }
          }
        }
      }
    },
    "/analytics": {
      "get": {
        "operationId": "getAnalytics",
        "summary": "Lost & Found figures",
        "tags": [
          "Lost & Found"
        ],
        "security": [
          {
            "apiKey": [
              "analytics:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                7,
                30,
                90,
                365
              ],
              "default": 30
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Analytics"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/parcels": {
      "get": {
        "operationId": "listParcels",
        "summary": "List parcels",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "waiting",
                "collected",
                "returned"
              ]
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "description": "Only records changed at or after this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Part of the recipient's name or unit, the tracking number or sender, or the exact pickup code.",
            "schema": {
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Parcel"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createParcel",
        "summary": "Log a parcel",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "description": "Goes through the same matching, email and history as the desk. Refused with tracking_duplicate when a waiting parcel already has that tracking number.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipient_email": {
                    "type": "string",
                    "format": "email",
                    "description": "Matches the people list. Give this or recipient_name."
                  },
                  "recipient_name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "unit": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "carrier": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "tracking": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "sender": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "shelf": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "notify": {
                    "type": "boolean",
                    "description": "Email the recipient their pickup code now. Defaults to true."
                  },
                  "handling_tags": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "perishable",
                        "fragile",
                        "oversized",
                        "signature_required",
                        "high_value"
                      ]
                    }
                  },
                  "hold_until": {
                    "type": "string",
                    "format": "date",
                    "description": "Do not remind before this date."
                  },
                  "stay_id": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "A stay id from GET /stays at this venue."
                  },
                  "room_at_event": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 60,
                    "description": "Room at the moment this record was logged. Defaults to the stay current room and does not change on a later room move."
                  },
                  "custom_values": {
                    "type": "object",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean",
                        "null"
                      ]
                    },
                    "description": "vFound Enterprise custom attributes, by field key (see the fields in Settings, Custom attributes). Unknown keys, values of the wrong type and choices outside the field's options are refused with 422. Send null or an empty string to clear a value. Required fields are enforced on the workspace forms, never on the API. After the plan ends new values are refused with 422; stored values stay."
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Parcel"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/parcels/{id}": {
      "get": {
        "operationId": "getParcel",
        "summary": "Get a parcel",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Parcel"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/parcels/{id}/collect": {
      "post": {
        "operationId": "collectParcel",
        "summary": "Hand a parcel over",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "collected_by": {
                    "type": "string",
                    "description": "Who collected it.",
                    "maxLength": 120
                  },
                  "signature": {
                    "type": "string",
                    "description": "A PNG data URL of their signature."
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [
                  "collected_by"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Parcel"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/parcels/{id}/return": {
      "post": {
        "operationId": "returnParcel",
        "summary": "Return a parcel to the sender",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "note": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Parcel"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/parcels/{id}/remind": {
      "post": {
        "operationId": "remindParcel",
        "summary": "Remind the recipient",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "description": "Emails the recipient a reminder to collect a waiting parcel. Refused with no_email when they have no email address.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Parcel"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/checkroom/tickets": {
      "get": {
        "operationId": "listCheckroomTickets",
        "summary": "List checkroom tickets",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "in",
                "returned",
                "left",
                "moved"
              ]
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "description": "Only records changed at or after this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Part of the guest's name or room, the ticket number, or the exact ticket code.",
            "schema": {
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CheckroomTicket"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "checkIn",
        "summary": "Check something in",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "description": "Gives the next free number. Refused with capacity_full when every number is in use.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "coat",
                      "bag",
                      "luggage",
                      "other"
                    ]
                  },
                  "pieces": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 20
                  },
                  "guest_name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "guest_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "guest_room": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "collect_by": {
                    "type": "string",
                    "format": "date-time",
                    "description": "For luggage."
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "fee_method": {
                    "type": "string",
                    "enum": [
                      "cash",
                      "card"
                    ]
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "es",
                      "fr",
                      "de",
                      "nl",
                      "it",
                      "pt",
                      "pl",
                      "sv",
                      "tr",
                      "ja",
                      "zh",
                      "ar"
                    ]
                  },
                  "photo": {
                    "type": "string",
                    "description": "A base64 data URL."
                  },
                  "station_id": {
                    "type": "integer"
                  },
                  "event_id": {
                    "type": "integer"
                  },
                  "storage_location": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "piece_details": {
                    "type": "array",
                    "maxItems": 20,
                    "description": "Optional per-piece type and storage location. When supplied, include exactly one row for every piece.",
                    "items": {
                      "type": "object",
                      "properties": {
                        "kind": {
                          "type": "string",
                          "enum": [
                            "coat",
                            "bag",
                            "luggage",
                            "other"
                          ]
                        },
                        "storage_location": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "maxLength": 100
                        }
                      },
                      "required": [
                        "kind"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "custom_values": {
                    "type": "object",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean",
                        "null"
                      ]
                    },
                    "description": "vFound Enterprise custom attributes, by field key (see the fields in Settings, Custom attributes). Unknown keys, values of the wrong type and choices outside the field's options are refused with 422. Send null or an empty string to clear a value. Required fields are enforced on the workspace forms, never on the API. After the plan ends new values are refused with 422; stored values stay."
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [
                  "kind"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CheckroomTicket"
                    },
                    "guest_ticket": {
                      "type": "object",
                      "description": "The guest's private ticket, returned only here: show the url as a QR code or print it for the guest. Reads, lists and webhooks never include it.",
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Six-character code the guest can show at the desk."
                        },
                        "url": {
                          "type": "string",
                          "format": "uri",
                          "description": "The guest's private ticket page."
                        }
                      },
                      "required": [
                        "code",
                        "url"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "data",
                    "guest_ticket"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/checkroom/tickets/{id}": {
      "get": {
        "operationId": "getCheckroomTicket",
        "summary": "Get a checkroom ticket",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CheckroomTicket"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/checkroom/tickets/{id}/hand-back": {
      "post": {
        "operationId": "handBack",
        "summary": "Hand it back",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "without_ticket": {
                    "type": "boolean",
                    "description": "The guest lost their ticket and the desk checked who they are. Needs collected_by and signature."
                  },
                  "collected_by": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "signature": {
                    "type": "string",
                    "description": "A PNG data URL."
                  },
                  "piece_ids": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 20,
                    "uniqueItems": true,
                    "description": "Return only these open pieces. Omit to return every open piece on the ticket.",
                    "items": {
                      "type": "integer"
                    }
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CheckroomTicket"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/loans": {
      "get": {
        "operationId": "listLoans",
        "summary": "List equipment handed out",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "out",
                "returned",
                "lost",
                "overdue"
              ]
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "description": "Only records changed at or after this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Part of the borrower's name, email or reference.",
            "schema": {
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Loan"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "handOutEquipment",
        "summary": "Hand equipment out",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "description": "Give item_id or item_code. Refused with item_out, item_in_repair or item_retired when it cannot go out.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "item_id": {
                    "type": "integer"
                  },
                  "item_code": {
                    "type": "string",
                    "description": "The code on its label, or the address its QR code holds.",
                    "maxLength": 300
                  },
                  "borrower_name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "borrower_email": {
                    "type": "string",
                    "format": "email",
                    "description": "Gets a receipt with the due time."
                  },
                  "borrower_reference": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "due_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Defaults to the item's usual time out."
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "es",
                      "fr",
                      "de",
                      "nl",
                      "it",
                      "pt",
                      "pl",
                      "sv",
                      "tr",
                      "ja",
                      "zh",
                      "ar"
                    ]
                  },
                  "signature": {
                    "type": "string",
                    "description": "A PNG data URL."
                  },
                  "person_id": {
                    "type": "integer",
                    "description": "An active person id from the shared people list."
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [
                  "borrower_name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Loan"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/loans/{id}": {
      "get": {
        "operationId": "getLoan",
        "summary": "Get a loan",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Loan"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/loans/{id}/return": {
      "post": {
        "operationId": "returnLoan",
        "summary": "Take equipment back",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "condition": {
                    "type": "string",
                    "enum": [
                      "good",
                      "damaged",
                      "incomplete"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "set_aside": {
                    "type": "boolean",
                    "description": "Put the item aside for repair."
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Loan"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/loans/returns": {
      "post": {
        "operationId": "returnLoans",
        "summary": "Take several equipment loans back together",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "loan_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "minItems": 1,
                    "maxItems": 50,
                    "uniqueItems": true,
                    "description": "The loans to take back."
                  },
                  "condition": {
                    "type": "string",
                    "enum": [
                      "good",
                      "damaged",
                      "incomplete"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "set_aside": {
                    "type": "boolean",
                    "description": "Put the item aside for repair."
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [
                  "loan_ids"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Loan"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "description": "Takes back 1 to 50 loans in one step, all or nothing: if one is already back (code already_back) or is not found at this venue, nothing changes. A borrower with an email address gets one return receipt per checkout listing everything that came back, and each loan sends its own loan.returned event."
      }
    },
    "/loans/{id}/extend": {
      "post": {
        "operationId": "extendLoan",
        "summary": "Give more time",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "description": "Emails the borrower the new due time. A time outside the desk's opening hours moves to the next opening; a time that would run over another booking of the item, or take the last free one in its category, is refused with reservation_conflict.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "due_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "The new due time, in the future."
                  }
                },
                "required": [
                  "due_at"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Loan"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/loans/checkouts": {
      "post": {
        "operationId": "createEquipmentCheckout",
        "summary": "Hand out one or more equipment items",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "description": "Atomically checks out individual items or a saved kit; no partial handover is possible.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "item_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "minItems": 1,
                    "maxItems": 50,
                    "uniqueItems": true
                  },
                  "item_id": {
                    "type": "integer"
                  },
                  "kit_id": {
                    "type": "integer"
                  },
                  "reservation_id": {
                    "type": "integer"
                  },
                  "borrower_id": {
                    "type": "integer"
                  },
                  "borrower_name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "borrower_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "borrower_ref": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "locale": {
                    "type": "string",
                    "enum": [
                      "en",
                      "es",
                      "fr",
                      "de",
                      "nl",
                      "it",
                      "pt",
                      "pl",
                      "sv",
                      "tr",
                      "ja",
                      "zh",
                      "ar"
                    ]
                  },
                  "due_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "signature": {
                    "type": "string"
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [
                  "item_ids",
                  "item_id",
                  "kit_id",
                  "reservation_id",
                  "borrower_id",
                  "borrower_name",
                  "borrower_email",
                  "borrower_ref",
                  "locale",
                  "due_at",
                  "note",
                  "signature"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentCheckout"
                    },
                    "emailed": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "data",
                    "emailed"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/kits": {
      "get": {
        "operationId": "listEquipmentKits",
        "summary": "List saved equipment kits",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EquipmentKit"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "createEquipmentKit",
        "summary": "Save an equipment kit",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "item_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "minItems": 2,
                    "maxItems": 50,
                    "uniqueItems": true
                  },
                  "active": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "name",
                  "item_ids"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentKit"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/kits/{id}": {
      "put": {
        "operationId": "updateEquipmentKit",
        "summary": "Update an equipment kit",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "item_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "minItems": 2,
                    "maxItems": 50,
                    "uniqueItems": true
                  },
                  "active": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "name",
                  "item_ids"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentKit"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/reservations": {
      "get": {
        "operationId": "listEquipmentReservations",
        "summary": "List equipment reservations",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "approved",
                "ready",
                "collected",
                "cancelled"
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EquipmentReservation"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createEquipmentReservation",
        "summary": "Reserve equipment",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "loan_item_id": {
                    "type": "integer"
                  },
                  "category": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "borrower_id": {
                    "type": "integer"
                  },
                  "borrower_name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "borrower_email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email"
                  },
                  "borrower_ref": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 80
                  },
                  "locale": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "en",
                      "es",
                      "fr",
                      "de",
                      "nl",
                      "it",
                      "pt",
                      "pl",
                      "sv",
                      "tr",
                      "ja",
                      "zh",
                      "ar",
                      null
                    ]
                  },
                  "starts_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "ends_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "note": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 500
                  }
                },
                "required": [
                  "starts_at",
                  "ends_at"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentReservation"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/reservations/{id}/approve": {
      "post": {
        "operationId": "approveEquipmentReservation",
        "summary": "Approve an equipment reservation",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentReservation"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "description": "A part of a kit or cart is approved with every other open part, all or none."
      }
    },
    "/loans/reservations/{id}/cancel": {
      "post": {
        "operationId": "cancelEquipmentReservation",
        "summary": "Cancel an equipment reservation",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentReservation"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "description": "A part of a kit or cart is cancelled with every other open part."
      }
    },
    "/loans/reservations/{id}/pickup": {
      "post": {
        "operationId": "collectEquipmentReservation",
        "summary": "Hand over reserved equipment",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "signature": {
                    "type": "string"
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [
                  "signature"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentCheckout"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "description": "A part of a kit or cart is collected with every other open part, in one checkout."
      }
    },
    "/loans/reservation-groups": {
      "post": {
        "operationId": "createEquipmentReservationGroup",
        "summary": "Reserve a kit or cart",
        "tags": [
          "Equipment"
        ],
        "description": "Books every part for the same borrower and times in one step, by the same rules and capacity checks as a single reservation, each part counted against the others. If any part is not available nothing is reserved, and the answer (422, kit_unavailable) names each part that is not. If any part's category needs approval, every part waits for it. Approving, cancelling or collecting any part (the reservation endpoints) acts on every open part; collecting gives each part of a category an available item and hands everything out in one checkout.",
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "borrower_id": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "A person on the people list; their name, email and reference are used."
                  },
                  "borrower_name": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Required unless borrower_id is sent."
                  },
                  "borrower_email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email"
                  },
                  "borrower_ref": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 80
                  },
                  "locale": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "en",
                      "es",
                      "fr",
                      "de",
                      "nl",
                      "it",
                      "pt",
                      "pl",
                      "sv",
                      "tr",
                      "ja",
                      "zh",
                      "ar",
                      null
                    ]
                  },
                  "starts_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "ends_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "note": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 500
                  },
                  "kit_id": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "An active kit: every item in it is reserved, as the kit is when the booking is made. Send either kit_id or items, not both."
                  },
                  "items": {
                    "type": [
                      "array",
                      "null"
                    ],
                    "minItems": 1,
                    "maxItems": 50,
                    "description": "A cart instead of a kit: each line is one exact item (loan_item_id) or a category with how many (quantity, default 1; one booking per unit, each given an item when it is handed out). Up to 50 units in all. Send either items or kit_id, not both.",
                    "items": {
                      "type": "object",
                      "properties": {
                        "loan_item_id": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "category": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "maxLength": 60
                        },
                        "quantity": {
                          "type": [
                            "integer",
                            "null"
                          ],
                          "minimum": 1,
                          "maximum": 50,
                          "description": "For a category line: how many. Ignored on an item line."
                        }
                      },
                      "oneOf": [
                        {
                          "required": [
                            "loan_item_id"
                          ],
                          "properties": {
                            "loan_item_id": {
                              "type": "integer"
                            },
                            "category": {
                              "type": "null"
                            }
                          }
                        },
                        {
                          "required": [
                            "category"
                          ],
                          "properties": {
                            "category": {
                              "type": "string",
                              "minLength": 1
                            },
                            "loan_item_id": {
                              "type": "null"
                            }
                          }
                        }
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "starts_at",
                  "ends_at"
                ],
                "additionalProperties": false,
                "oneOf": [
                  {
                    "required": [
                      "kit_id"
                    ],
                    "properties": {
                      "kit_id": {
                        "type": "integer"
                      },
                      "items": {
                        "type": "null"
                      }
                    }
                  },
                  {
                    "required": [
                      "items"
                    ],
                    "properties": {
                      "items": {
                        "type": "array"
                      },
                      "kit_id": {
                        "type": "null"
                      }
                    }
                  }
                ],
                "anyOf": [
                  {
                    "required": [
                      "borrower_id"
                    ],
                    "properties": {
                      "borrower_id": {
                        "type": "integer"
                      }
                    }
                  },
                  {
                    "required": [
                      "borrower_name"
                    ],
                    "properties": {
                      "borrower_name": {
                        "type": "string",
                        "minLength": 1
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentReservationGroup"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "422": {
            "description": "Not valid, or not available. kit_unavailable lists each part that is not available in unavailable; nothing was reserved.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/loans/closures": {
      "get": {
        "operationId": "listEquipmentClosures",
        "summary": "List equipment desk closures",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EquipmentClosure"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "addEquipmentClosure",
        "summary": "Add an equipment desk closure",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "description": "Whole days in the venue's time zone, up to 366 days. It applies to new reservations, checkouts and extensions; bookings made before keep their times.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "starts_on": {
                    "type": "string",
                    "format": "date"
                  },
                  "ends_on": {
                    "type": "string",
                    "format": "date"
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 120,
                    "description": "Internal staff note."
                  },
                  "public_message": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 300,
                    "description": "Optional message shown to borrowers, independent of the internal note."
                  }
                },
                "required": [
                  "starts_on",
                  "ends_on"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentClosure"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/closures/{id}": {
      "delete": {
        "operationId": "deleteEquipmentClosure",
        "summary": "Remove an equipment desk closure",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/rules": {
      "get": {
        "operationId": "listEquipmentRules",
        "summary": "List equipment rules",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "defaults": {
                      "type": "object",
                      "properties": {
                        "max_items": {
                          "type": "integer"
                        },
                        "block_when_overdue": {
                          "type": "boolean"
                        },
                        "opening_hours": {
                          "type": [
                            "object",
                            "array",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "max_items",
                        "block_when_overdue",
                        "opening_hours"
                      ],
                      "additionalProperties": false
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EquipmentRule"
                      }
                    },
                    "closures": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EquipmentClosure"
                      },
                      "description": "Closure dates that have not ended yet."
                    }
                  },
                  "required": [
                    "defaults",
                    "data",
                    "closures"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "saveEquipmentRule",
        "summary": "Save an equipment category rule",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "category": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "loan_hours": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "max_items": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "approval_required": {
                    "type": "boolean"
                  },
                  "block_when_overdue": {
                    "type": "boolean"
                  },
                  "buffer_before_minutes": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 1440,
                    "description": "Optional. Leave it out to keep the saved value; 0 or null turns it off."
                  },
                  "buffer_after_minutes": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 1440,
                    "description": "Optional. Leave it out to keep the saved value; 0 or null turns it off."
                  },
                  "notice_minutes": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 43200,
                    "description": "Optional. Leave it out to keep the saved value; 0 or null turns it off."
                  },
                  "advance_days": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 730,
                    "description": "Optional. Leave it out to keep the saved value; null turns it off."
                  }
                },
                "required": [
                  "category",
                  "approval_required",
                  "block_when_overdue"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentRule"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentRule"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/maintenance": {
      "get": {
        "operationId": "listEquipmentMaintenance",
        "summary": "List equipment maintenance",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "item_id",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "due",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EquipmentMaintenance"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "logEquipmentMaintenance",
        "summary": "Log equipment maintenance",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "loan_item_id": {
                    "type": "integer"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "service",
                      "inspection",
                      "repair",
                      "note"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "serviced_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "due_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": [
                  "loan_item_id",
                  "kind",
                  "note"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentMaintenance"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/stocktakes": {
      "get": {
        "operationId": "listEquipmentStocktakes",
        "summary": "List equipment stock-takes",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EquipmentStocktake"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "startEquipmentStocktake",
        "summary": "Start an equipment stock-take",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentStocktake"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/stocktakes/{id}/scan": {
      "post": {
        "operationId": "scanEquipmentStocktake",
        "summary": "Scan equipment into a stock-take",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "maxLength": 300
                  }
                },
                "required": [
                  "code"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentStocktake"
                    },
                    "item": {
                      "$ref": "#/components/schemas/EquipmentItem"
                    }
                  },
                  "required": [
                    "data",
                    "item"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/stocktakes/{id}/finish": {
      "post": {
        "operationId": "finishEquipmentStocktake",
        "summary": "Finish an equipment stock-take",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentStocktake"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/import": {
      "post": {
        "operationId": "importEquipmentItems",
        "summary": "Preview or import an equipment CSV",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "csv": {
                    "type": "string",
                    "maxLength": 1048576
                  },
                  "preset": {
                    "type": "string",
                    "enum": [
                      "vfound",
                      "snipeit",
                      "sortly",
                      "cheqroom"
                    ]
                  },
                  "dry_run": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "csv",
                  "preset"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "properties": {
                        "dry_run": {
                          "const": true
                        },
                        "valid": {
                          "type": "integer"
                        },
                        "sample": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "additionalProperties": true
                          }
                        }
                      },
                      "required": [
                        "dry_run",
                        "valid",
                        "sample"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "object",
                      "properties": {
                        "dry_run": {
                          "const": false
                        },
                        "created": {
                          "type": "integer"
                        },
                        "updated": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "dry_run",
                        "created",
                        "updated"
                      ],
                      "additionalProperties": false
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/loans/items": {
      "get": {
        "operationId": "listEquipment",
        "summary": "List equipment",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "available",
                "out",
                "repair",
                "retired"
              ]
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Part of its name or asset tag, or the exact label code.",
            "schema": {
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "description": "Only records changed at or after this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EquipmentItem"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createEquipment",
        "summary": "Add equipment",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 110
                  },
                  "category": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "tag": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "location": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "notes": {
                    "type": "string",
                    "maxLength": 500
                  },
                  "loan_hours": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 2160
                  },
                  "copies": {
                    "type": "integer",
                    "description": "Add several identical items at once, numbered.",
                    "minimum": 1,
                    "maximum": 50
                  },
                  "photo": {
                    "type": "string",
                    "description": "A base64 data URL."
                  },
                  "custom_values": {
                    "type": "object",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean",
                        "null"
                      ]
                    },
                    "description": "vFound Enterprise custom attributes, by field key (see the fields in Settings, Custom attributes). Unknown keys, values of the wrong type and choices outside the field's options are refused with 422. Send null or an empty string to clear a value. Required fields are enforced on the workspace forms, never on the API. After the plan ends new values are refused with 422; stored values stay."
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EquipmentItem"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/loans/items/{id}": {
      "get": {
        "operationId": "getEquipment",
        "summary": "Get equipment",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentItem"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updateEquipment",
        "summary": "Update equipment",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "category": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "tag": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "location": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "notes": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "loan_hours": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "available",
                      "repair",
                      "retired"
                    ]
                  },
                  "custom_values": {
                    "type": "object",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean",
                        "null"
                      ]
                    },
                    "description": "vFound Enterprise custom attributes, by field key (see the fields in Settings, Custom attributes). Unknown keys, values of the wrong type and choices outside the field's options are refused with 422. Send null or an empty string to clear a value. Required fields are enforced on the workspace forms, never on the API. After the plan ends new values are refused with 422; stored values stay."
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentItem"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitors": {
      "get": {
        "operationId": "listVisits",
        "summary": "List visits",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "expected",
                "in",
                "out",
                "cancelled",
                "missed"
              ]
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "description": "Only records changed at or after this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "search",
            "in": "query",
            "description": "Part of the visitor's name, email or company, the host's name, or the exact pass code.",
            "schema": {
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Visit"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createVisit",
        "summary": "Invite or sign in a visitor",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "visitor_name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "visitor_email": {
                    "type": "string",
                    "format": "email",
                    "description": "Gets their pass."
                  },
                  "visitor_company": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "purpose": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "host_email": {
                    "type": "string",
                    "format": "email",
                    "description": "Matched to the people list; the host is told when the visitor arrives."
                  },
                  "host_name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "arriving_now": {
                    "type": "boolean",
                    "description": "Sign them in now instead of inviting them."
                  },
                  "expected_at": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Required unless arriving_now."
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "es",
                      "fr",
                      "de",
                      "nl",
                      "it",
                      "pt",
                      "pl",
                      "sv",
                      "tr",
                      "ja",
                      "zh",
                      "ar"
                    ]
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "agreed": {
                    "type": "boolean",
                    "description": "They agreed to your visitor terms."
                  },
                  "visitor_type_id": {
                    "type": "integer"
                  },
                  "answers": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "valid_from": {
                    "type": "string",
                    "format": "date"
                  },
                  "valid_until": {
                    "type": "string",
                    "format": "date"
                  },
                  "recurrence": {
                    "type": "string",
                    "enum": [
                      "once",
                      "daily",
                      "weekdays"
                    ]
                  },
                  "photo": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "A JPEG, PNG or WebP data URL, under 8 MB. vFound re-encodes it, removes metadata and keeps it private to the venue workspace and printed badge."
                  },
                  "identity_checked": {
                    "type": "boolean",
                    "description": "Authenticated venue staff attest that they visually checked a physical photo ID. vFound stores the staff member and time, never an ID image or number."
                  },
                  "custom_values": {
                    "type": "object",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean",
                        "null"
                      ]
                    },
                    "description": "vFound Enterprise custom attributes, by field key (see the fields in Settings, Custom attributes). Unknown keys, values of the wrong type and choices outside the field's options are refused with 422. Send null or an empty string to clear a value. Required fields are enforced on the workspace forms, never on the API. After the plan ends new values are refused with 422; stored values stay."
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [
                  "visitor_name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Visit"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitors/{id}": {
      "get": {
        "operationId": "getVisit",
        "summary": "Get a visit",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Visit"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitors/{id}/sign-in": {
      "post": {
        "operationId": "signInVisit",
        "summary": "Sign a visitor in",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "agreed": {
                    "type": "boolean"
                  },
                  "photo": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "A JPEG, PNG or WebP data URL, under 8 MB. vFound re-encodes it, removes metadata and keeps it private to the venue workspace and printed badge."
                  },
                  "identity_checked": {
                    "type": "boolean",
                    "description": "Authenticated venue staff attest that they visually checked a physical photo ID. vFound stores the staff member and time, never an ID image or number."
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Visit"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitors/{id}/sign-out": {
      "post": {
        "operationId": "signOutVisit",
        "summary": "Sign a visitor out",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Visit"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/visitors/{id}/cancel": {
      "post": {
        "operationId": "cancelVisit",
        "summary": "Cancel an invitation",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Visit"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitors/{id}/send-pass": {
      "post": {
        "operationId": "sendVisitorPass",
        "summary": "Email the pass again",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Visit"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/people": {
      "get": {
        "operationId": "listPeople",
        "summary": "List people",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "description": "Part of their name, email, unit or reference.",
            "schema": {
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "updated_since",
            "in": "query",
            "description": "Only records changed at or after this time.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Person"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createPerson",
        "summary": "Add a person",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "unit": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "reference": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "language": {
                    "type": "string",
                    "enum": [
                      "en",
                      "es",
                      "fr",
                      "de",
                      "nl",
                      "it",
                      "pt",
                      "pl",
                      "sv",
                      "tr",
                      "ja",
                      "zh",
                      "ar"
                    ]
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Person"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/people/upsert": {
      "post": {
        "operationId": "upsertPeople",
        "summary": "Add or update up to 500 people",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:write"
            ]
          }
        ],
        "description": "People whose email is already on the list are updated; the rest are added.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "people": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 500,
                    "items": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string",
                          "maxLength": 120
                        },
                        "email": {
                          "type": "string",
                          "format": "email"
                        },
                        "unit": {
                          "type": "string",
                          "maxLength": 60
                        },
                        "reference": {
                          "type": "string",
                          "maxLength": 60
                        },
                        "language": {
                          "type": "string",
                          "enum": [
                            "en",
                            "es",
                            "fr",
                            "de",
                            "nl",
                            "it",
                            "pt",
                            "pl",
                            "sv",
                            "tr",
                            "ja",
                            "zh",
                            "ar"
                          ]
                        }
                      },
                      "required": [
                        "name"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "people"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "added": {
                          "type": "integer"
                        },
                        "updated": {
                          "type": "integer"
                        },
                        "skipped": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "added",
                        "updated",
                        "skipped"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/people/{id}": {
      "get": {
        "operationId": "getPerson",
        "summary": "Get a person",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Person"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updatePerson",
        "summary": "Update a person",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email"
                  },
                  "unit": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 60
                  },
                  "reference": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 60
                  },
                  "language": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "en",
                      "es",
                      "fr",
                      "de",
                      "nl",
                      "it",
                      "pt",
                      "pl",
                      "sv",
                      "tr",
                      "ja",
                      "zh",
                      "ar"
                    ]
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Person"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deletePerson",
        "summary": "Remove a person",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:write"
            ]
          }
        ],
        "description": "Their parcels, visits and loans keep their name but are no longer linked.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "summary": "List webhook addresses",
        "description": "Only the addresses this key created. Addresses added in Settings, or by another key, are not listed.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "apiKey": [
              "webhooks:manage"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "createWebhook",
        "summary": "Subscribe an address to events",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "apiKey": [
              "webhooks:manage"
            ]
          }
        ],
        "description": "For tools such as Zapier. Up to 25 addresses per venue. Each event needs the read scope of its product (claims:read for claim events, people:read for person and people list events, visitors:read for visit, visitor type, kiosk and courier events, and so on); other events are refused with 422.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Accepted, but this answer carries something shown only once, so it is never stored: a retry runs the request again. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "A public HTTPS address on port 443.",
                    "maxLength": 500
                  },
                  "events": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "string",
                      "enum": [
                        "item.created",
                        "item.updated",
                        "item.disposition_recorded",
                        "item.match_updated",
                        "item.transfer_sent",
                        "item.transfer_cancelled",
                        "item.transfer_received",
                        "claim.created",
                        "claim.status_changed",
                        "claim.ownership_reviewed",
                        "claim.decision_recorded",
                        "claim.release_approved",
                        "claim.handover_recorded",
                        "lost_report.updated",
                        "lost_report.closed",
                        "lost_report.contact_updated",
                        "lost_report.created",
                        "lost_report.match_updated",
                        "parcel.logged",
                        "parcel.updated",
                        "parcel.reminded",
                        "parcel.collected",
                        "parcel.returned",
                        "parcel.recipient_arrived",
                        "parcel.reminders_snoozed",
                        "parcel.held",
                        "parcel.proxy_created",
                        "parcel.pickup_served",
                        "parcel.escalated",
                        "parcel.outgoing_logged",
                        "parcel.outgoing_handed_over",
                        "parcel.round_created",
                        "parcel.round_delivered",
                        "checkroom.checked_in",
                        "checkroom.handed_back",
                        "checkroom.left",
                        "checkroom.self_checkin_started",
                        "checkroom.ready_requested",
                        "checkroom.ready",
                        "checkroom.station_created",
                        "checkroom.station_updated",
                        "checkroom.event_created",
                        "checkroom.event_updated",
                        "loan.checked_out",
                        "loan.due_soon",
                        "loan.overdue",
                        "loan.extended",
                        "loan.returned",
                        "loan.lost",
                        "loan.checkout_created",
                        "loan.self_checkout",
                        "loan.kit_created",
                        "loan.kit_updated",
                        "loan.reservation_requested",
                        "loan.reservation_created",
                        "loan.reservation_approved",
                        "loan.reservation_ready",
                        "loan.reservation_cancelled",
                        "loan.reservation_collected",
                        "loan.extension_requested",
                        "loan.problem_reported",
                        "loan.rule_updated",
                        "loan.maintenance_logged",
                        "loan.maintenance_due",
                        "loan.stocktake_started",
                        "loan.stocktake_completed",
                        "loan.items_imported",
                        "loan.transfer_prepared",
                        "loan.transfer_sent",
                        "loan.transfer_received",
                        "loan.transfer_rejected",
                        "loan.transfer_cancelled",
                        "loan.transfer_exception",
                        "loan.transfer_lost",
                        "visit.expected",
                        "visit.signed_in",
                        "visit.host_confirmed",
                        "visit.signed_out",
                        "visit.cancelled",
                        "visit.approval_requested",
                        "visit.approved",
                        "visit.denied",
                        "visit.host_replied",
                        "visit.roll_call_started",
                        "visit.roll_call_completed",
                        "visitor_type.created",
                        "visitor_type.updated",
                        "visitor_type.deactivated",
                        "kiosk.paired",
                        "kiosk.revoked",
                        "courier.signed_in",
                        "courier.signed_out",
                        "person.created",
                        "person.updated",
                        "person.deactivated",
                        "person.deleted",
                        "people.sync.completed",
                        "people.sync.failed"
                      ]
                    }
                  }
                },
                "required": [
                  "url",
                  "events"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/NewWebhook"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            },
            "headers": {
              "Location": {
                "description": "The path of the new webhook subscription. Send DELETE to this path to unsubscribe.",
                "schema": {
                  "type": "string",
                  "example": "/api/v1/webhooks/42"
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "delete": {
        "operationId": "deleteWebhook",
        "summary": "Remove a webhook address",
        "description": "Only an address this key created; any other address answers 404.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "apiKey": [
              "webhooks:manage"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/people/export": {
      "get": {
        "operationId": "exportPeople",
        "summary": "Export people as CSV",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Formula-safe CSV export",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/people/{id}/send-my-vfound": {
      "post": {
        "operationId": "sendMyVfound",
        "summary": "Email My vFound",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:write"
            ]
          }
        ],
        "description": "Emails an active person the signed private page for their linked records.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "sent": {
                          "type": "boolean",
                          "const": true
                        }
                      },
                      "required": [
                        "sent"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/people/sync-source": {
      "get": {
        "operationId": "getPeopleSyncSource",
        "summary": "Get connected directory",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "oneOf": [
                        {
                          "type": "object",
                          "properties": {
                            "url": {
                              "type": "string",
                              "format": "uri"
                            },
                            "host": {
                              "type": "string"
                            },
                            "mode": {
                              "type": "string",
                              "enum": [
                                "upsert",
                                "mirror"
                              ]
                            },
                            "enabled": {
                              "type": "boolean"
                            },
                            "last_started_at": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "date-time"
                            },
                            "last_succeeded_at": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "date-time"
                            },
                            "last_row_count": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "last_added": {
                              "type": "integer"
                            },
                            "last_updated": {
                              "type": "integer"
                            },
                            "last_deactivated": {
                              "type": "integer"
                            },
                            "last_skipped": {
                              "type": "integer"
                            },
                            "last_error": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "mode",
                            "enabled",
                            "host",
                            "last_added",
                            "last_updated",
                            "last_deactivated",
                            "last_skipped"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "put": {
        "operationId": "savePeopleSyncSource",
        "summary": "Save connected directory",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:write"
            ]
          }
        ],
        "description": "The CSV link must use public HTTPS. Its value is encrypted in storage.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 2048
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "upsert",
                      "mirror"
                    ]
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "url",
                  "mode"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "url": {
                          "type": "string",
                          "format": "uri"
                        },
                        "host": {
                          "type": "string"
                        },
                        "mode": {
                          "type": "string",
                          "enum": [
                            "upsert",
                            "mirror"
                          ]
                        },
                        "enabled": {
                          "type": "boolean"
                        },
                        "last_started_at": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time"
                        },
                        "last_succeeded_at": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time"
                        },
                        "last_row_count": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "last_added": {
                          "type": "integer"
                        },
                        "last_updated": {
                          "type": "integer"
                        },
                        "last_deactivated": {
                          "type": "integer"
                        },
                        "last_skipped": {
                          "type": "integer"
                        },
                        "last_error": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "required": [
                        "mode",
                        "enabled",
                        "host",
                        "last_added",
                        "last_updated",
                        "last_deactivated",
                        "last_skipped"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deletePeopleSyncSource",
        "summary": "Remove connected directory",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "const": true
                    }
                  },
                  "required": [
                    "deleted"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/people/sync-source/run": {
      "post": {
        "operationId": "runPeopleSyncSource",
        "summary": "Run connected directory",
        "tags": [
          "People"
        ],
        "security": [
          {
            "apiKey": [
              "people:write"
            ]
          }
        ],
        "description": "Fetches the saved CSV now. Mirror mode stops if the valid row count falls by more than 30 percent.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "source": {
                          "type": "object",
                          "properties": {
                            "url": {
                              "type": "string",
                              "format": "uri"
                            },
                            "host": {
                              "type": "string"
                            },
                            "mode": {
                              "type": "string",
                              "enum": [
                                "upsert",
                                "mirror"
                              ]
                            },
                            "enabled": {
                              "type": "boolean"
                            },
                            "last_started_at": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "date-time"
                            },
                            "last_succeeded_at": {
                              "type": [
                                "string",
                                "null"
                              ],
                              "format": "date-time"
                            },
                            "last_row_count": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "last_added": {
                              "type": "integer"
                            },
                            "last_updated": {
                              "type": "integer"
                            },
                            "last_deactivated": {
                              "type": "integer"
                            },
                            "last_skipped": {
                              "type": "integer"
                            },
                            "last_error": {
                              "type": [
                                "string",
                                "null"
                              ]
                            }
                          },
                          "required": [
                            "mode",
                            "enabled",
                            "host",
                            "last_added",
                            "last_updated",
                            "last_deactivated",
                            "last_skipped"
                          ],
                          "additionalProperties": false
                        },
                        "result": {
                          "type": "object",
                          "properties": {
                            "rows": {
                              "type": "integer"
                            },
                            "added": {
                              "type": "integer"
                            },
                            "updated": {
                              "type": "integer"
                            },
                            "deactivated": {
                              "type": "integer"
                            },
                            "skipped": {
                              "type": "integer"
                            },
                            "managed": {
                              "type": "integer",
                              "description": "Rows skipped because another connected directory manages that person. Included in skipped."
                            },
                            "conflicts": {
                              "type": "integer",
                              "description": "Rows skipped because their email belongs to a person on the list whose directory ID the row does not match (another ID, or none in the row), to more than one person, or to a person already matched to another row, and rows whose directory ID matches a person but whose email belongs to someone else. The people concerned are left unchanged. Included in skipped."
                            }
                          },
                          "required": [
                            "rows",
                            "added",
                            "updated",
                            "deactivated",
                            "skipped"
                          ],
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "source",
                        "result"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitors/{id}/approve": {
      "post": {
        "operationId": "approveVisit",
        "summary": "Approve a visit request",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Visit"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitors/{id}/deny": {
      "post": {
        "operationId": "denyVisit",
        "summary": "Deny a visit request",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Visit"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitors/{id}/badge": {
      "get": {
        "operationId": "downloadVisitorBadge",
        "summary": "Download a browser-printable visitor badge",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitor-types": {
      "get": {
        "operationId": "listVisitorTypes",
        "summary": "List visitor types",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/VisitorType"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "createVisitorType",
        "summary": "Create a visitor type",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "guest",
                      "interview",
                      "contractor",
                      "delivery",
                      "custom"
                    ]
                  },
                  "badge_color": {
                    "type": "string",
                    "pattern": "^#[0-9a-fA-F]{6}$"
                  },
                  "approval_required": {
                    "type": "boolean"
                  },
                  "retention_days": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 7,
                    "maximum": 365,
                    "description": "Days finished visits of this type are kept; null follows the venue default."
                  },
                  "active": {
                    "type": "boolean"
                  },
                  "terms": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "questions": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "label": {
                          "type": "string"
                        },
                        "required": {
                          "type": "boolean"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "text",
                            "dropdown",
                            "checkbox",
                            "date"
                          ],
                          "default": "text"
                        },
                        "options": {
                          "type": "array",
                          "maxItems": 30,
                          "items": {
                            "type": "string",
                            "maxLength": 100
                          },
                          "description": "Required non-empty choices for dropdown questions."
                        }
                      },
                      "required": [
                        "key",
                        "label",
                        "required"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "photo_required": {
                    "type": "boolean"
                  },
                  "identity_check_required": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "name",
                  "kind",
                  "badge_color",
                  "approval_required"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/VisitorType"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitor-types/{id}": {
      "patch": {
        "operationId": "updateVisitorType",
        "summary": "Update a visitor type",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "guest",
                      "interview",
                      "contractor",
                      "delivery",
                      "custom"
                    ]
                  },
                  "badge_color": {
                    "type": "string",
                    "pattern": "^#[0-9a-fA-F]{6}$"
                  },
                  "approval_required": {
                    "type": "boolean"
                  },
                  "retention_days": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 7,
                    "maximum": 365,
                    "description": "Days finished visits of this type are kept; null follows the venue default."
                  },
                  "active": {
                    "type": "boolean"
                  },
                  "terms": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "questions": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "type": "object",
                      "properties": {
                        "key": {
                          "type": "string"
                        },
                        "label": {
                          "type": "string"
                        },
                        "required": {
                          "type": "boolean"
                        },
                        "type": {
                          "type": "string",
                          "enum": [
                            "text",
                            "dropdown",
                            "checkbox",
                            "date"
                          ],
                          "default": "text"
                        },
                        "options": {
                          "type": "array",
                          "maxItems": 30,
                          "items": {
                            "type": "string",
                            "maxLength": 100
                          },
                          "description": "Required non-empty choices for dropdown questions."
                        }
                      },
                      "required": [
                        "key",
                        "label",
                        "required"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "photo_required": {
                    "type": "boolean"
                  },
                  "identity_check_required": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "name",
                  "kind",
                  "badge_color",
                  "approval_required",
                  "retention_days",
                  "active",
                  "terms",
                  "questions"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/VisitorType"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deactivateVisitorType",
        "summary": "Deactivate a visitor type",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/VisitorType"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitor-roll-call": {
      "get": {
        "operationId": "getVisitorRollCall",
        "summary": "Get the latest live roll call",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/RollCall"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "startVisitorRollCall",
        "summary": "Start a live roll call",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "include_expected": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "include_expected"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/RollCall"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitor-roll-call/entries/{entry}": {
      "patch": {
        "operationId": "markVisitorRollCallEntry",
        "summary": "Mark a visitor safe or missing",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "entry",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "safe",
                      "missing"
                    ]
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/RollCallEntry"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitor-roll-call/{id}/finish": {
      "post": {
        "operationId": "finishVisitorRollCall",
        "summary": "Finish a live roll call",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/RollCall"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitor-kiosks": {
      "get": {
        "operationId": "listVisitorKiosks",
        "summary": "List paired and pending kiosk devices",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Kiosk"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/visitor-kiosks/pairing": {
      "post": {
        "operationId": "createVisitorKioskPairing",
        "summary": "Create a ten-minute kiosk pairing code",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Accepted, but this answer carries something shown only once, so it is never stored: a retry runs the request again. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "actions": {
                    "type": "array",
                    "description": "What the kiosk may do. Defaults to visitors.sign_in and visitors.sign_out. Another product's action needs that product switched on and the key's write scope for it.",
                    "items": {
                      "type": "string",
                      "enum": [
                        "visitors.sign_in",
                        "visitors.sign_out",
                        "parcels.arrive",
                        "loans.self_checkout",
                        "checkroom.self_checkin",
                        "lost_found.report"
                      ]
                    }
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/KioskPairing"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitor-kiosks/{id}": {
      "delete": {
        "operationId": "revokeVisitorKiosk",
        "summary": "Revoke a kiosk device",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "deleted"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/visitor-analytics": {
      "get": {
        "operationId": "getVisitorAnalytics",
        "summary": "Visitor analytics for the last year, or the days asked for",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/VisitorAnalytics"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "description": "The last N days on the venue's calendar, ending today.",
            "schema": {
              "type": "integer",
              "minimum": 7,
              "maximum": 365,
              "default": 365
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/visitor-registration": {
      "get": {
        "operationId": "getVisitorRegistration",
        "summary": "Get the self-registration link",
        "tags": [
          "Visitors"
        ],
        "security": [
          {
            "apiKey": [
              "visitors:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/VisitorRegistration"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/parcels/couriers": {
      "get": {
        "operationId": "listCouriersOnSite",
        "summary": "List couriers logged through Visitors",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Courier"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "in",
                "out"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/parcels/tracking": {
      "post": {
        "operationId": "detectParcelTracking",
        "summary": "Detect a carrier from a tracking number",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "tracking": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "carrier": {
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "standard": {
                          "type": "string",
                          "enum": [
                            "GS1"
                          ]
                        },
                        "identifiers": {
                          "type": "object",
                          "properties": {
                            "sscc": {
                              "type": "string"
                            },
                            "gtin": {
                              "type": "string"
                            },
                            "lot": {
                              "type": "string"
                            },
                            "expiry_yymmdd": {
                              "type": "string"
                            },
                            "serial": {
                              "type": "string"
                            }
                          },
                          "additionalProperties": false
                        }
                      },
                      "required": [
                        "tracking",
                        "carrier"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "description": "Normalises a scanned carrier number and detects common carriers. A valid GS1 SSCC is returned as shipment tracking with its checked identifier; GS1 product identifiers are identified but never treated as shipment tracking.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tracking": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/parcels/pickup-queue": {
      "get": {
        "operationId": "getParcelPickupQueue",
        "summary": "Read the live pickup queue",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/parcels/pickup-queue/{id}/serve": {
      "post": {
        "operationId": "serveParcelPickup",
        "summary": "Mark a pickup request served",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/parcels/bulk-remind": {
      "post": {
        "operationId": "bulkRemindParcels",
        "summary": "Remind selected parcel recipients",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "minItems": 1,
                    "maxItems": 200
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/parcels/bulk-return": {
      "post": {
        "operationId": "bulkReturnParcels",
        "summary": "Return selected parcels to sender",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "minItems": 1,
                    "maxItems": 200
                  },
                  "note": {
                    "type": "string"
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/parcels/shelves": {
      "get": {
        "operationId": "listParcelShelves",
        "summary": "List shelf occupancy",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "saveParcelShelf",
        "summary": "Create or update a parcel shelf",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "capacity": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/parcels/analytics": {
      "get": {
        "operationId": "getParcelAnalytics",
        "summary": "Read parcel analytics",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "description": "The last N days on the venue's calendar, ending today.",
            "schema": {
              "type": "integer",
              "minimum": 7,
              "maximum": 365,
              "default": 30
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/parcels/outgoing": {
      "get": {
        "operationId": "listOutgoingParcels",
        "summary": "List outgoing parcels",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "createOutgoingParcel",
        "summary": "Log an outgoing parcel",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipient_name": {
                    "type": "string"
                  },
                  "carrier": {
                    "type": "string"
                  },
                  "tracking": {
                    "type": "string"
                  },
                  "notes": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/parcels/outgoing/{id}/handoff": {
      "post": {
        "operationId": "handoffOutgoingParcel",
        "summary": "Record an outgoing courier handoff",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "courier_name": {
                    "type": "string"
                  },
                  "signature": {
                    "type": "string",
                    "description": "A PNG signature data URL."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/parcels/rounds": {
      "get": {
        "operationId": "listParcelRounds",
        "summary": "List parcel delivery rounds",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "createParcelRound",
        "summary": "Create a parcel delivery round",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "scheduled_for": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "parcel_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "minItems": 1,
                    "maxItems": 200
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/parcels/rounds/{round}/stops/{stop}/deliver": {
      "post": {
        "operationId": "deliverParcelRoundStop",
        "summary": "Complete a parcel round stop",
        "tags": [
          "Parcels"
        ],
        "security": [
          {
            "apiKey": [
              "parcels:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "round",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "stop",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "delivered_to": {
                    "type": "string"
                  },
                  "signature": {
                    "type": "string",
                    "description": "A PNG signature data URL."
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/checkroom/stations": {
      "get": {
        "operationId": "listCheckroomStations",
        "summary": "List checkroom stations",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "createCheckroomStation",
        "summary": "Create a checkroom station",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "number_start": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9999
                  },
                  "number_end": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9999
                  },
                  "storage_locations": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 100
                    },
                    "maxItems": 100,
                    "uniqueItems": true
                  },
                  "active": {
                    "type": "boolean"
                  },
                  "piece_capacity": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 100000
                  },
                  "location_capacities": {
                    "type": [
                      "object",
                      "array",
                      "null"
                    ],
                    "additionalProperties": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 100000
                    },
                    "maxProperties": 100,
                    "propertyNames": {
                      "minLength": 1,
                      "maxLength": 100
                    }
                  }
                },
                "required": [
                  "name",
                  "number_start",
                  "number_end"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/checkroom/stations/{id}": {
      "put": {
        "operationId": "updateCheckroomStation",
        "summary": "Update a checkroom station",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "number_start": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9999
                  },
                  "number_end": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 9999
                  },
                  "storage_locations": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 100
                    },
                    "maxItems": 100,
                    "uniqueItems": true
                  },
                  "active": {
                    "type": "boolean"
                  },
                  "piece_capacity": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 100000
                  },
                  "location_capacities": {
                    "type": [
                      "object",
                      "array",
                      "null"
                    ],
                    "additionalProperties": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 100000
                    },
                    "maxProperties": 100,
                    "propertyNames": {
                      "minLength": 1,
                      "maxLength": 100
                    }
                  }
                },
                "required": [
                  "name",
                  "number_start",
                  "number_end"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/checkroom/events": {
      "get": {
        "operationId": "listCheckroomEvents",
        "summary": "List checkroom events",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "createCheckroomEvent",
        "summary": "Create a checkroom event",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "starts_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "ends_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "expected_volume": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 100000
                  },
                  "station_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "maxItems": 50,
                    "uniqueItems": true
                  }
                },
                "required": [
                  "name",
                  "starts_at",
                  "ends_at"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/checkroom/events/{id}": {
      "put": {
        "operationId": "updateCheckroomEvent",
        "summary": "Update a checkroom event",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "starts_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "ends_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "expected_volume": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 1,
                    "maximum": 100000
                  },
                  "station_ids": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    },
                    "maxItems": 50,
                    "uniqueItems": true
                  }
                },
                "required": [
                  "name",
                  "starts_at",
                  "ends_at"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "additionalProperties": true
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/checkroom/exit-queue": {
      "get": {
        "operationId": "listCheckroomExitQueue",
        "summary": "List the checkroom exit queue",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    },
                    "checked_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "oldest_wait_minutes": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "description": "Oldest outstanding not-ready request in whole minutes, null when none."
                    }
                  },
                  "required": [
                    "data",
                    "checked_at"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/checkroom/tickets/{id}/ready": {
      "post": {
        "operationId": "markCheckroomReady",
        "summary": "Mark a checkroom ticket ready",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CheckroomTicket"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/checkroom/report": {
      "get": {
        "operationId": "getCheckroomReport",
        "summary": "Read checkroom operations report",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "days",
            "in": "query",
            "description": "The last N days on the venue's calendar, ending today. Used when from and to are not sent.",
            "schema": {
              "type": "integer",
              "minimum": 7,
              "maximum": 365
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/checkroom/export": {
      "get": {
        "operationId": "exportCheckroomReport",
        "summary": "Export checkroom operations CSV",
        "tags": [
          "Checkroom"
        ],
        "security": [
          {
            "apiKey": [
              "checkroom:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "CSV export",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Invalid request.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/stays": {
      "get": {
        "operationId": "listStays",
        "summary": "List private stay context",
        "tags": [
          "Stays"
        ],
        "security": [
          {
            "apiKey": [
              "stays:read"
            ]
          }
        ],
        "description": "Search by guest, stable reference or current room. A room match is navigation only and never an ownership suggestion.",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 120
            }
          },
          {
            "name": "state",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "expected",
                "in_house",
                "departed",
                "cancelled",
                "unknown"
              ]
            }
          },
          {
            "name": "source",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "manual",
                "import",
                "api"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 5,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/HotelStay"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Meta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "upsertStay",
        "summary": "Create or update stay context",
        "tags": [
          "Stays"
        ],
        "security": [
          {
            "apiKey": [
              "stays:write"
            ]
          }
        ],
        "description": "Upserts by venue, API source and stable stay reference. An update with a source_updated_at no newer than the saved event is acknowledged but not applied.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "external_stay_ref": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "external_guest_ref": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 120
                  },
                  "guest_name": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "arrival_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "departure_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "source_timezone": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "current_room": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 60
                  },
                  "stay_state": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "expected",
                      "in_house",
                      "departed",
                      "cancelled",
                      "unknown",
                      null
                    ]
                  },
                  "source_updated_at": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  }
                },
                "required": [
                  "external_stay_ref",
                  "guest_name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "200": {
            "description": "Existing source record updated, or an older/equal replay safely ignored.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/HotelStay"
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "applied": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "applied"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "201": {
            "description": "Source record created.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/HotelStay"
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "applied": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "applied"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/stays/{stay}": {
      "get": {
        "operationId": "getStay",
        "summary": "Get private stay context and history",
        "tags": [
          "Stays"
        ],
        "security": [
          {
            "apiKey": [
              "stays:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "stay",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/HotelStay"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/loans/transfers": {
      "get": {
        "operationId": "listEquipmentTransfers",
        "summary": "List equipment transfers",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "enabled": {
                      "type": "boolean"
                    },
                    "can_manage": {
                      "type": "boolean"
                    },
                    "destinations": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EquipmentTransfer"
                      }
                    }
                  },
                  "required": [
                    "enabled",
                    "can_manage",
                    "destinations",
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "operationId": "prepareEquipmentTransfer",
        "summary": "Prepare an equipment transfer",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "item_id": {
                    "type": "integer"
                  },
                  "destination_business_id": {
                    "type": "integer"
                  },
                  "destination_location": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "service_business_id": {
                    "type": "integer"
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "required": [
                  "item_id",
                  "destination_business_id",
                  "destination_location"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentTransfer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/transfers/{id}/send": {
      "post": {
        "operationId": "sendEquipmentTransfer",
        "summary": "Send an equipment transfer",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentTransfer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/transfers/{id}/receive": {
      "post": {
        "operationId": "receiveEquipmentTransfer",
        "summary": "Receive an equipment transfer",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "arrival_status": {
                    "type": "string",
                    "enum": [
                      "available",
                      "repair"
                    ]
                  },
                  "location": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "required": [
                  "arrival_status"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentTransfer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/transfers/{id}/cancel": {
      "post": {
        "operationId": "cancelEquipmentTransfer",
        "summary": "Cancel a prepared equipment transfer",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentTransfer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/transfers/{id}/reject": {
      "post": {
        "operationId": "rejectEquipmentTransfer",
        "summary": "Reject a prepared equipment transfer",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "required": [],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentTransfer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/loans/transfers/{id}/exception": {
      "post": {
        "operationId": "reportEquipmentTransferException",
        "summary": "Report an in-transit equipment problem",
        "tags": [
          "Equipment"
        ],
        "security": [
          {
            "apiKey": [
              "loans:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "A unique retry key; repeating the same key and body within 24 hours returns the first answer. After finder or claimant personal-data erasure, saved venue responses return 410 without erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "note": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "required": [
                  "note"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/EquipmentTransfer"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/lost-reports/{id}/matches": {
      "get": {
        "operationId": "getReportMatches",
        "summary": "Find candidate items for a report",
        "tags": [
          "Lost & Found"
        ],
        "description": "Up to24 live text/category candidates, with label, reason and source. Fresh cached AI verdicts are labelled cached_ai; fallback possible is a text-search suggestion. Does not call a model, create a claim or decide ownership. Closed reports return an empty list. Needs both the items:read and lost_reports:read scopes, because it returns items and lost reports.",
        "security": [
          {
            "apiKey": [
              "lost_reports:read",
              "items:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ReportMatch"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/items/{id}/matches": {
      "get": {
        "operationId": "getItemMatches",
        "summary": "Find candidate lost reports for an item",
        "tags": [
          "Lost & Found"
        ],
        "description": "Up to24 matches from the latest1000 open reports. Returns report id and title without reporter contact details. Labels/reasons distinguish fresh cached AI from text search; no model request, claim creation or ownership decision. Needs both the items:read and lost_reports:read scopes, because it returns items and lost reports.",
        "security": [
          {
            "apiKey": [
              "items:read",
              "lost_reports:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ItemMatch"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/claims/{id}/verification": {
      "post": {
        "operationId": "recordOwnershipReview",
        "summary": "Record a human ownership review",
        "tags": [
          "Lost & Found"
        ],
        "description": "Named manager attestation for an undecided claim; no automatic document authentication and no document copies/free-text evidence stored. The latest review must pass before API acceptance. Does not accept or release the item.",
        "security": [
          {
            "apiKey": [
              "claims:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/OwnershipReview"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "409": {
            "description": "An email is being sent for this claim or its guest. Nothing changed; retry after the send finishes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "verified": {
                    "type": "boolean"
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "distinctive_details",
                      "purchase_proof",
                      "staff_review"
                    ]
                  }
                },
                "required": [
                  "verified",
                  "method"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/claims/{id}/decision": {
      "post": {
        "operationId": "recordClaimDecision",
        "summary": "Record a human claim decision or return stage",
        "tags": [
          "Lost & Found"
        ],
        "description": "Runs the workspace state machine. Acceptance requires a successful recorded human ownership review; release approval, live competing claims and complete manual-shipping fields still apply. Use /handover for in-person collection. A claim whose own courier collects it (arranged_by owner) cannot be marked shipped; the team records that handover in the workspace. This is not an MCP tool. When a return chosen with accepted cannot follow yet (a high-value release still needs its second approval), the answer carries return_notice saying why.",
        "security": [
          {
            "apiKey": [
              "claims:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Claim"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "409": {
            "description": "An email is being sent for this claim or its guest. Nothing changed; retry after the send finishes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "open",
                      "accepted",
                      "rejected",
                      "expired",
                      "ready_for_pickup",
                      "ready_for_shipment",
                      "shipped"
                    ]
                  },
                  "return": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "pickup",
                      "shipment",
                      null
                    ],
                    "description": "Only with accepted: how the item gets back. The claim then moves on to ready_for_pickup or ready_for_shipment in the same request and the claimant gets one email, for that final step, which says the claim was approved. When a high-value release still needs its second approval the claim stays accepted and the claimant gets the approval email. Without it the claim stays accepted."
                  },
                  "arranged_by": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "venue",
                      "owner",
                      null
                    ],
                    "description": "With ready_for_shipment (or return shipment): who books the courier. venue: the team posts it (address, carrier and tracking before shipped). owner: the claimant books their own courier, no address is asked for, and the team records the courier company when it collects the item. Without it, the venue's Lost & Found setting."
                  },
                  "shipment": {
                    "type": "object",
                    "properties": {
                      "recipient_name": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "line1": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "line2": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "city": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "region": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "postal_code": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "country": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "carrier": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "tracking_number": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    },
                    "additionalProperties": false
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/claims/{id}/release-approval": {
      "post": {
        "operationId": "approveClaimRelease",
        "summary": "Record a second manager release approval",
        "tags": [
          "Lost & Found"
        ],
        "description": "The same owner/manager and different-approver checks as the workspace. Only an accepted claim may be approved. Does not hand over property.",
        "security": [
          {
            "apiKey": [
              "claims:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ClaimCustody"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "409": {
            "description": "An email is being sent for this claim or its guest. Nothing changed; retry after the send finishes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/claims/{id}/custody": {
      "get": {
        "operationId": "getClaimCustody",
        "summary": "Read claim custody and review history",
        "tags": [
          "Lost & Found"
        ],
        "description": "Review and state history, release approver and pickup name/time. signature_recorded is a boolean: no signature image, private file path or document is exposed. Erased guest details stay erased.",
        "security": [
          {
            "apiKey": [
              "claims:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ClaimCustody"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/claims/{id}/handover": {
      "post": {
        "operationId": "recordClaimHandover",
        "summary": "Record physical pickup",
        "tags": [
          "Lost & Found"
        ],
        "description": "Ready-for-pickup claims only. Records collector name and time; if the venue requires a signature, include a PNG data URL. High-value second approval and paid-return restrictions cannot be bypassed. Repeated closed calls do not replace the first receipt.",
        "security": [
          {
            "apiKey": [
              "claims:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ClaimCustody"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "409": {
            "description": "An email is being sent for this claim or its guest. Nothing changed; retry after the send finishes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handover": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "maxLength": 120
                      },
                      "signature": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "maxLength": 400000
                      }
                    },
                    "required": [
                      "name"
                    ],
                    "additionalProperties": false
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [
                  "handover"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/items/{id}/disposition": {
      "post": {
        "operationId": "recordItemDisposition",
        "summary": "Record donation or disposal with a batch receipt",
        "tags": [
          "Lost & Found"
        ],
        "description": "Only eligible items after their holding date or already expired; pending/accepted claims block disposition. Donation needs a named recipient. Uses the workspace batch service and audit trail.",
        "security": [
          {
            "apiKey": [
              "items:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Send any unique value to make a retry safe: the same key and body within 24 hours returns the first answer instead of running twice. After finder or claimant personal-data erasure, saved venue responses return 410 without the erased details; refresh the record.",
            "schema": {
              "type": "string",
              "maxLength": 191
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "401": {
            "description": "No valid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The key lacks the scope, the product is not open, or the venue is paused.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "More than 120 requests a minute for this key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found at this venue.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Invalid fields, or a conflict with the record's state (see code).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ItemDisposition"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "donated",
                      "disposed"
                    ]
                  },
                  "recipient": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 191
                  },
                  "notes": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 1000
                  },
                  "checklist": {
                    "$ref": "#/components/schemas/ChecklistAnswers"
                  }
                },
                "required": [
                  "kind"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/lost-found/desk-settings": {
      "get": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Read optional desk settings.",
        "operationId": "deskGetLostFoundDeskSettings",
        "security": [
          {
            "apiKey": [
              "lost_reports:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LostFoundDeskSettings"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "put": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Replace desk settings; owner or manager only. New mail settings default off.",
        "operationId": "deskPutLostFoundDeskSettings",
        "security": [
          {
            "apiKey": [
              "lost_reports:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LostFoundDeskSettings"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "industry": {
                    "type": "string",
                    "enum": [
                      "none",
                      "airport",
                      "transit",
                      "event",
                      "hotel",
                      "campus",
                      "hospital",
                      "mall",
                      "attraction"
                    ]
                  },
                  "progress_days": {
                    "type": "integer",
                    "enum": [
                      0,
                      3,
                      7,
                      14
                    ]
                  },
                  "ended_email": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "industry",
                  "progress_days",
                  "ended_email"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/checkroom/desk-settings": {
      "get": {
        "tags": [
          "Checkroom"
        ],
        "summary": "Read optional desk settings.",
        "operationId": "deskGetCheckroomDeskSettings",
        "security": [
          {
            "apiKey": [
              "checkroom:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CheckroomDeskSettings"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "put": {
        "tags": [
          "Checkroom"
        ],
        "summary": "Replace desk settings; owner or manager only. New mail settings default off.",
        "operationId": "deskPutCheckroomDeskSettings",
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CheckroomDeskSettings"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reminder_minutes": {
                    "type": "integer",
                    "enum": [
                      0,
                      15,
                      30,
                      60,
                      120
                    ]
                  },
                  "collection_receipts": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "reminder_minutes",
                  "collection_receipts"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/lost-found/counts": {
      "get": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "List the latest 30 scan-count sessions.",
        "operationId": "deskGetLostFoundCounts",
        "security": [
          {
            "apiKey": [
              "items:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LfCountSummary"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Snapshot held item identifiers for a report-only count; no custody changes.",
        "operationId": "deskPostLostFoundCounts",
        "security": [
          {
            "apiKey": [
              "items:write"
            ]
          }
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LfCountResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "bin_id": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/lost-found/counts/{id}": {
      "get": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Read a count with missing, unexpected and no-longer-here figures.",
        "operationId": "deskGetLostFoundCountsId",
        "security": [
          {
            "apiKey": [
              "items:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LfCountResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/lost-found/counts/{id}/scan": {
      "post": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Record a QR or short item-label scan; duplicate known items count once.",
        "operationId": "deskPostLostFoundCountsIdScan",
        "security": [
          {
            "apiKey": [
              "items:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LfCountResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          },
          "409": {
            "description": "Session is already finished; it cannot accept scans."
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "required": [
                  "code"
                ]
              }
            }
          }
        }
      }
    },
    "/lost-found/counts/{id}/finish": {
      "post": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Finish a count without changing items.",
        "operationId": "deskPostLostFoundCountsIdFinish",
        "security": [
          {
            "apiKey": [
              "items:write"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LfCountResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {}
              }
            }
          }
        }
      }
    },
    "/lost-found/queues": {
      "get": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "List the current key creator’s saved work queues in this venue.",
        "operationId": "deskGetLostFoundQueues",
        "security": [
          {
            "apiKey": [
              "lost_reports:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LfWorkQueue"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Save a named work-queue preset for the current key creator.",
        "operationId": "deskPostLostFoundQueues",
        "security": [
          {
            "apiKey": [
              "lost_reports:write"
            ]
          }
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LfWorkQueue"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "preset": {
                    "type": "string",
                    "enum": [
                      "unreviewed",
                      "awaiting_guest",
                      "expiring",
                      "transfer_awaiting_receipt"
                    ]
                  }
                },
                "required": [
                  "name",
                  "preset"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/lost-found/queues/{id}": {
      "get": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Read current records behind a saved queue. Incoming transfers open the existing permissioned transfer view.",
        "operationId": "deskGetLostFoundQueuesId",
        "security": [
          {
            "apiKey": [
              "lost_reports:read",
              "items:read",
              "claims:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LfQueueResult"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "put": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Replace the current key creator’s saved work queue in this venue.",
        "operationId": "deskPutLostFoundQueuesId",
        "security": [
          {
            "apiKey": [
              "lost_reports:write"
            ]
          }
        ],
        "responses": {
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          },
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LfWorkQueue"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "preset": {
                    "type": "string",
                    "enum": [
                      "unreviewed",
                      "awaiting_guest",
                      "expiring",
                      "transfer_awaiting_receipt"
                    ]
                  }
                },
                "required": [
                  "name",
                  "preset"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "delete": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Delete the current key creator’s saved work queue in this venue.",
        "operationId": "deskDeleteLostFoundQueuesId",
        "security": [
          {
            "apiKey": [
              "lost_reports:write"
            ]
          }
        ],
        "responses": {
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          },
          "204": {
            "description": "Deleted. Underlying records are unchanged."
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/lost-found/intake-review": {
      "post": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Return deterministic completeness and privacy prompts; no AI or mutations.",
        "operationId": "deskPostLostFoundIntakeReview",
        "security": [
          {
            "apiKey": [
              "items:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 191
                  },
                  "location": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 191
                  },
                  "description": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 10000
                  },
                  "internal_notes": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 10000
                  },
                  "tags": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 2000
                  },
                  "show_image": {
                    "type": "boolean"
                  },
                  "bin_id": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/checkroom/templates": {
      "get": {
        "tags": [
          "Checkroom"
        ],
        "summary": "List configuration-only setup templates; manager only.",
        "operationId": "deskGetCheckroomTemplates",
        "security": [
          {
            "apiKey": [
              "checkroom:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CheckroomTemplate"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "post": {
        "tags": [
          "Checkroom"
        ],
        "summary": "Save an event’s station configuration without guests or tickets; manager only.",
        "operationId": "deskPostCheckroomTemplates",
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CheckroomTemplate"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "event_id": {
                    "type": "integer"
                  }
                },
                "required": [
                  "name",
                  "event_id"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/checkroom/templates/{id}/apply": {
      "post": {
        "tags": [
          "Checkroom"
        ],
        "summary": "Create a new event and stations; active number-range collisions reject the entire operation.",
        "operationId": "deskPostCheckroomTemplatesIdApply",
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "responses": {
          "201": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CheckroomTemplateEvent"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 60
                  },
                  "starts_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "ends_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "number_offset": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 9998
                  }
                },
                "required": [
                  "name",
                  "starts_at",
                  "ends_at",
                  "number_offset"
                ]
              }
            }
          }
        }
      }
    },
    "/checkroom/templates/{id}": {
      "put": {
        "tags": [
          "Checkroom"
        ],
        "summary": "Replace a configuration-only setup template; manager only.",
        "operationId": "deskPutCheckroomTemplatesId",
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "responses": {
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          },
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/CheckroomTemplate"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "event_id": {
                    "type": "integer"
                  }
                },
                "required": [
                  "name",
                  "event_id"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      },
      "delete": {
        "tags": [
          "Checkroom"
        ],
        "summary": "Delete a configuration-only setup template; manager only.",
        "operationId": "deskDeleteCheckroomTemplatesId",
        "security": [
          {
            "apiKey": [
              "checkroom:write"
            ]
          }
        ],
        "responses": {
          "403": {
            "description": "Membership, manager role, product or scope refused."
          },
          "404": {
            "description": "Record not in the authorized venue."
          },
          "422": {
            "description": "Validation failed."
          },
          "401": {
            "description": "Authentication refused."
          },
          "429": {
            "description": "API key rate limit exceeded."
          },
          "204": {
            "description": "Deleted. Underlying records are unchanged."
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/loans/timeline": {
      "get": {
        "tags": [
          "Equipment"
        ],
        "operationId": "equipmentTimeline",
        "summary": "Check one additional whole-day item or category booking",
        "description": "Read-only EquipmentCapacity check under the venue lock. Each cell checks one new booking for the whole local day, from now for today. true means available, false unavailable, null uncertain. Adjacent available cells do not guarantee a continuous booking. Page size 50. Requires loans:read.",
        "x-required-scope": "loans:read",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive venue-local date. Up to 31 dates, today through next year."
          },
          {
            "name": "until",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive venue-local date. Up to 31 dates, today through next year."
          },
          {
            "name": "item_id",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Item in this venue only."
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 60
            },
            "description": "Exact current category."
          },
          {
            "name": "group",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "item",
                "category"
              ],
              "default": "item"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "Venue-scoped results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": [
                              "integer",
                              "string",
                              "null"
                            ]
                          },
                          "name": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "category": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "slots": {
                            "type": "array",
                            "items": {
                              "type": [
                                "boolean",
                                "null"
                              ]
                            }
                          }
                        }
                      }
                    },
                    "days": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": "string",
                            "format": "date"
                          },
                          "from": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "until": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer"
                    },
                    "last_page": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "Missing loans:read scope or Equipment access"
          },
          "422": {
            "description": "Invalid date range, filter or foreign item"
          }
        },
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ]
      }
    },
    "/loans/warranties": {
      "get": {
        "tags": [
          "Equipment"
        ],
        "operationId": "equipmentWarranties",
        "summary": "Filter recorded equipment warranty dates",
        "description": "Soon includes today through 30 days ahead. Expired is before today. Retired items remain visible. The API never subscribes a person to reminders; personal opt-in is in the workspace. Requires loans:read.",
        "x-required-scope": "loans:read",
        "parameters": [
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 60
            },
            "description": "Exact current category."
          },
          {
            "name": "filter",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "soon",
                "expired",
                "all"
              ],
              "default": "soon"
            }
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "Venue-scoped results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "category": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "warranty_until": {
                            "type": "string",
                            "format": "date"
                          }
                        }
                      }
                    },
                    "page": {
                      "type": "integer"
                    },
                    "last_page": {
                      "type": "integer"
                    },
                    "subscribed": {
                      "type": "boolean",
                      "description": "Personal workspace opt-in, false for API-key requests."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "Missing loans:read scope or Equipment access"
          },
          "422": {
            "description": "Invalid date range, filter or foreign item"
          }
        },
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ]
      }
    },
    "/loans/utilization": {
      "get": {
        "tags": [
          "Equipment"
        ],
        "operationId": "equipmentUtilization",
        "summary": "Report elapsed per-asset utilization within recorded status history",
        "description": "Exact integer seconds. tracked = downtime + unavailable + available; available = borrowed + idle. Repair status records service/repair downtime; transfers/transit/retired are other unavailable time. Only recorded status intervals for items currently in this venue count. Prior downtime is unknown. Borrowed time uses actual checkout/return timestamps, not due dates. CSV exports hours to six decimal places. Requires loans:read.",
        "x-required-scope": "loans:read",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive venue-local date. Last 365 days, capped at now."
          },
          {
            "name": "until",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive venue-local date. Last 365 days, capped at now."
          },
          {
            "name": "item_id",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1
            },
            "description": "Item in this venue only."
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 60
            },
            "description": "Exact current category."
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ],
              "default": "json"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "responses": {
          "200": {
            "description": "Venue-scoped results",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "code": {
                            "type": "string"
                          },
                          "category": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "observed_from": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "utilization_percent": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "tracked_seconds": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "downtime_seconds": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "unavailable_seconds": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "available_seconds": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "borrowed_seconds": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "idle_seconds": {
                            "type": "integer",
                            "minimum": 0
                          }
                        }
                      }
                    },
                    "from": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "until": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "totals": {
                      "type": "object",
                      "properties": {
                        "tracked_seconds": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "downtime_seconds": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "unavailable_seconds": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "available_seconds": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "borrowed_seconds": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "idle_seconds": {
                          "type": "integer",
                          "minimum": 0
                        }
                      }
                    }
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key"
          },
          "403": {
            "description": "Missing loans:read scope or Equipment access"
          },
          "422": {
            "description": "Invalid date range, filter or foreign item"
          }
        },
        "security": [
          {
            "apiKey": [
              "loans:read"
            ]
          }
        ]
      }
    },
    "/lost-found/context-schema": {
      "get": {
        "tags": [
          "Lost & Found"
        ],
        "summary": "Read the selected private context field definitions. No record values.",
        "operationId": "getLostFoundContextSchema",
        "security": [
          {
            "apiKey": [
              "items:read"
            ]
          },
          {
            "apiKey": [
              "lost_reports:read"
            ]
          }
        ],
        "x-vfound-any-of-scopes": [
          "items:read",
          "lost_reports:read"
        ],
        "responses": {
          "200": {
            "description": "Selected schema, effective collection switch and label/type definitions only.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LostFoundContextSchema"
                    }
                  },
                  "required": [
                    "data"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Authentication required"
          },
          "403": {
            "description": "No qualifying scope, product or membership"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ]
      }
    },
    "/lost-reports/{id}": {
      "put": {
        "operationId": "updateLostReport",
        "summary": "Update a private lost report with a current fingerprint",
        "description": "Human-operated edit of what was lost. Requires current venue writer membership and an open, watched, unerased report. Omitting journey preserves saved context; disabled context writes refuse. Contact changes use mailbox verification, never this route.",
        "tags": [
          "Lost reports"
        ],
        "security": [
          {
            "apiKey": [
              "lost_reports:write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/ActingUser"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "fingerprint",
                  "title",
                  "description"
                ],
                "properties": {
                  "fingerprint": {
                    "type": "string",
                    "minLength": 64,
                    "maxLength": 64
                  },
                  "title": {
                    "type": "string",
                    "maxLength": 191
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "category": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "colour_brand": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 191
                  },
                  "place_lost": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "maxLength": 191
                  },
                  "date_lost": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date"
                  },
                  "journey": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 100
                    }
                  },
                  "journey_schema": {
                    "type": "string",
                    "maxLength": 40
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Current private report",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/LostReport"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "Current writer permission required"
          },
          "404": {
            "description": "Report not in this venue"
          },
          "422": {
            "description": "Stale fingerprint, invalid fields, disabled context collection or report no longer editable"
          }
        }
      }
    }
  },
  "webhooks": {
    "item.created": {
      "post": {
        "summary": "item.created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.created"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Item"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "item.updated": {
      "post": {
        "summary": "item.updated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.updated"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Item"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "item.disposition_recorded": {
      "post": {
        "summary": "item.disposition_recorded",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.disposition_recorded"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Item"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        },
        "operationId": "onItemDispositionRecorded"
      }
    },
    "item.match_updated": {
      "post": {
        "summary": "item.match_updated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.match_updated"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "report_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "item_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "reason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "report_id",
                          "item_id",
                          "label",
                          "reason"
                        ],
                        "additionalProperties": false
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        },
        "operationId": "onItemMatchUpdated"
      }
    },
    "item.transfer_sent": {
      "post": {
        "summary": "item.transfer_sent",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.transfer_sent"
                      },
                      "data": {
                        "$ref": "#/components/schemas/ItemTransfer"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "item.transfer_cancelled": {
      "post": {
        "summary": "item.transfer_cancelled",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.transfer_cancelled"
                      },
                      "data": {
                        "$ref": "#/components/schemas/ItemTransfer"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "item.transfer_received": {
      "post": {
        "summary": "item.transfer_received",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.transfer_received"
                      },
                      "data": {
                        "$ref": "#/components/schemas/ItemTransfer"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "claim.created": {
      "post": {
        "summary": "claim.created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "claim.created"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Claim"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "claim.status_changed": {
      "post": {
        "summary": "claim.status_changed",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "claim.status_changed"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Claim"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "claim.ownership_reviewed": {
      "post": {
        "summary": "claim.ownership_reviewed",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "claim.ownership_reviewed"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Claim"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        },
        "operationId": "onClaimOwnershipReviewed"
      }
    },
    "claim.decision_recorded": {
      "post": {
        "summary": "claim.decision_recorded",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "claim.decision_recorded"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Claim"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        },
        "operationId": "onClaimDecisionRecorded"
      }
    },
    "claim.release_approved": {
      "post": {
        "summary": "claim.release_approved",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "claim.release_approved"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Claim"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        },
        "operationId": "onClaimReleaseApproved"
      }
    },
    "claim.handover_recorded": {
      "post": {
        "summary": "claim.handover_recorded",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "claim.handover_recorded"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Claim"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        },
        "operationId": "onClaimHandoverRecorded"
      }
    },
    "lost_report.updated": {
      "post": {
        "summary": "lost_report.updated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "lost_report.updated"
                      },
                      "data": {
                        "$ref": "#/components/schemas/LostReport"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "lost_report.closed": {
      "post": {
        "summary": "lost_report.closed",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "lost_report.closed"
                      },
                      "data": {
                        "$ref": "#/components/schemas/LostReport"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "lost_report.contact_updated": {
      "post": {
        "summary": "lost_report.contact_updated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "lost_report.contact_updated"
                      },
                      "data": {
                        "$ref": "#/components/schemas/LostReport"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "lost_report.created": {
      "post": {
        "summary": "lost_report.created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "lost_report.created"
                      },
                      "data": {
                        "$ref": "#/components/schemas/LostReport"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "lost_report.match_updated": {
      "post": {
        "summary": "lost_report.match_updated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "lost_report.match_updated"
                      },
                      "data": {
                        "type": "object",
                        "properties": {
                          "report_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "item_id": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "label": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "reason": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "report_id",
                          "item_id",
                          "label",
                          "reason"
                        ],
                        "additionalProperties": false
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        },
        "operationId": "onLostReportMatchUpdated"
      }
    },
    "parcel.logged": {
      "post": {
        "summary": "parcel.logged",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.logged"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Parcel"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.updated": {
      "post": {
        "summary": "parcel.updated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.updated"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Parcel"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.reminded": {
      "post": {
        "summary": "parcel.reminded",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.reminded"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Parcel"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.collected": {
      "post": {
        "summary": "parcel.collected",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.collected"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Parcel"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.returned": {
      "post": {
        "summary": "parcel.returned",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.returned"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Parcel"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.recipient_arrived": {
      "post": {
        "summary": "parcel.recipient_arrived",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.recipient_arrived"
                      },
                      "data": {
                        "type": "object"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.reminders_snoozed": {
      "post": {
        "summary": "parcel.reminders_snoozed",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.reminders_snoozed"
                      },
                      "data": {
                        "type": "object"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.held": {
      "post": {
        "summary": "parcel.held",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.held"
                      },
                      "data": {
                        "type": "object"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.proxy_created": {
      "post": {
        "summary": "parcel.proxy_created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.proxy_created"
                      },
                      "data": {
                        "type": "object"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.pickup_served": {
      "post": {
        "summary": "parcel.pickup_served",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.pickup_served"
                      },
                      "data": {
                        "type": "object"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.escalated": {
      "post": {
        "summary": "parcel.escalated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.escalated"
                      },
                      "data": {
                        "type": "object"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.outgoing_logged": {
      "post": {
        "summary": "parcel.outgoing_logged",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.outgoing_logged"
                      },
                      "data": {
                        "type": "object"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.outgoing_handed_over": {
      "post": {
        "summary": "parcel.outgoing_handed_over",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.outgoing_handed_over"
                      },
                      "data": {
                        "type": "object"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.round_created": {
      "post": {
        "summary": "parcel.round_created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.round_created"
                      },
                      "data": {
                        "type": "object"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "parcel.round_delivered": {
      "post": {
        "summary": "parcel.round_delivered",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "parcel.round_delivered"
                      },
                      "data": {
                        "type": "object"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "checkroom.checked_in": {
      "post": {
        "summary": "checkroom.checked_in",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "checkroom.checked_in"
                      },
                      "data": {
                        "$ref": "#/components/schemas/CheckroomTicket"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "checkroom.handed_back": {
      "post": {
        "summary": "checkroom.handed_back",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "checkroom.handed_back"
                      },
                      "data": {
                        "$ref": "#/components/schemas/CheckroomTicket"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "checkroom.left": {
      "post": {
        "summary": "checkroom.left",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "checkroom.left"
                      },
                      "data": {
                        "$ref": "#/components/schemas/CheckroomTicket"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "checkroom.self_checkin_started": {
      "post": {
        "summary": "checkroom.self_checkin_started",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "checkroom.self_checkin_started"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "checkroom.ready_requested": {
      "post": {
        "summary": "checkroom.ready_requested",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "checkroom.ready_requested"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "checkroom.ready": {
      "post": {
        "summary": "checkroom.ready",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "checkroom.ready"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "checkroom.station_created": {
      "post": {
        "summary": "checkroom.station_created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "checkroom.station_created"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "checkroom.station_updated": {
      "post": {
        "summary": "checkroom.station_updated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "checkroom.station_updated"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "checkroom.event_created": {
      "post": {
        "summary": "checkroom.event_created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "checkroom.event_created"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "checkroom.event_updated": {
      "post": {
        "summary": "checkroom.event_updated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "checkroom.event_updated"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.checked_out": {
      "post": {
        "summary": "loan.checked_out",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.checked_out"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Loan"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.due_soon": {
      "post": {
        "summary": "loan.due_soon",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.due_soon"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Loan"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.overdue": {
      "post": {
        "summary": "loan.overdue",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.overdue"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Loan"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.extended": {
      "post": {
        "summary": "loan.extended",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.extended"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Loan"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.returned": {
      "post": {
        "summary": "loan.returned",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.returned"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Loan"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.lost": {
      "post": {
        "summary": "loan.lost",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.lost"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Loan"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.checkout_created": {
      "post": {
        "summary": "loan.checkout_created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.checkout_created"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.self_checkout": {
      "post": {
        "summary": "loan.self_checkout",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.self_checkout"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.kit_created": {
      "post": {
        "summary": "loan.kit_created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.kit_created"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.kit_updated": {
      "post": {
        "summary": "loan.kit_updated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.kit_updated"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.reservation_requested": {
      "post": {
        "summary": "loan.reservation_requested",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.reservation_requested"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.reservation_created": {
      "post": {
        "summary": "loan.reservation_created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.reservation_created"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.reservation_approved": {
      "post": {
        "summary": "loan.reservation_approved",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.reservation_approved"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.reservation_ready": {
      "post": {
        "summary": "loan.reservation_ready",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.reservation_ready"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.reservation_cancelled": {
      "post": {
        "summary": "loan.reservation_cancelled",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.reservation_cancelled"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.reservation_collected": {
      "post": {
        "summary": "loan.reservation_collected",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.reservation_collected"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.extension_requested": {
      "post": {
        "summary": "loan.extension_requested",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.extension_requested"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.problem_reported": {
      "post": {
        "summary": "loan.problem_reported",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.problem_reported"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.rule_updated": {
      "post": {
        "summary": "loan.rule_updated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.rule_updated"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.maintenance_logged": {
      "post": {
        "summary": "loan.maintenance_logged",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.maintenance_logged"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.maintenance_due": {
      "post": {
        "summary": "loan.maintenance_due",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.maintenance_due"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.stocktake_started": {
      "post": {
        "summary": "loan.stocktake_started",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.stocktake_started"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.stocktake_completed": {
      "post": {
        "summary": "loan.stocktake_completed",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.stocktake_completed"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.items_imported": {
      "post": {
        "summary": "loan.items_imported",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.items_imported"
                      },
                      "data": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.transfer_prepared": {
      "post": {
        "summary": "loan.transfer_prepared",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.transfer_prepared"
                      },
                      "data": {
                        "$ref": "#/components/schemas/EquipmentTransfer"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.transfer_sent": {
      "post": {
        "summary": "loan.transfer_sent",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.transfer_sent"
                      },
                      "data": {
                        "$ref": "#/components/schemas/EquipmentTransfer"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.transfer_received": {
      "post": {
        "summary": "loan.transfer_received",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.transfer_received"
                      },
                      "data": {
                        "$ref": "#/components/schemas/EquipmentTransfer"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.transfer_rejected": {
      "post": {
        "summary": "loan.transfer_rejected",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.transfer_rejected"
                      },
                      "data": {
                        "$ref": "#/components/schemas/EquipmentTransfer"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.transfer_cancelled": {
      "post": {
        "summary": "loan.transfer_cancelled",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.transfer_cancelled"
                      },
                      "data": {
                        "$ref": "#/components/schemas/EquipmentTransfer"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.transfer_exception": {
      "post": {
        "summary": "loan.transfer_exception",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.transfer_exception"
                      },
                      "data": {
                        "$ref": "#/components/schemas/EquipmentTransfer"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "loan.transfer_lost": {
      "post": {
        "summary": "loan.transfer_lost",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "loan.transfer_lost"
                      },
                      "data": {
                        "$ref": "#/components/schemas/EquipmentTransfer"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visit.expected": {
      "post": {
        "summary": "visit.expected",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visit.expected"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Visit"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visit.signed_in": {
      "post": {
        "summary": "visit.signed_in",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visit.signed_in"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Visit"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visit.host_confirmed": {
      "post": {
        "summary": "visit.host_confirmed",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visit.host_confirmed"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Visit"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visit.signed_out": {
      "post": {
        "summary": "visit.signed_out",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visit.signed_out"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Visit"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visit.cancelled": {
      "post": {
        "summary": "visit.cancelled",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visit.cancelled"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Visit"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visit.approval_requested": {
      "post": {
        "summary": "visit.approval_requested",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visit.approval_requested"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Visit"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visit.approved": {
      "post": {
        "summary": "visit.approved",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visit.approved"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Visit"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visit.denied": {
      "post": {
        "summary": "visit.denied",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visit.denied"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Visit"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visit.host_replied": {
      "post": {
        "summary": "visit.host_replied",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visit.host_replied"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Visit"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visit.roll_call_started": {
      "post": {
        "summary": "visit.roll_call_started",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visit.roll_call_started"
                      },
                      "data": {
                        "$ref": "#/components/schemas/RollCall"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visit.roll_call_completed": {
      "post": {
        "summary": "visit.roll_call_completed",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visit.roll_call_completed"
                      },
                      "data": {
                        "$ref": "#/components/schemas/RollCall"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visitor_type.created": {
      "post": {
        "summary": "visitor_type.created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visitor_type.created"
                      },
                      "data": {
                        "$ref": "#/components/schemas/VisitorType"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visitor_type.updated": {
      "post": {
        "summary": "visitor_type.updated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visitor_type.updated"
                      },
                      "data": {
                        "$ref": "#/components/schemas/VisitorType"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "visitor_type.deactivated": {
      "post": {
        "summary": "visitor_type.deactivated",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "visitor_type.deactivated"
                      },
                      "data": {
                        "$ref": "#/components/schemas/VisitorType"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "kiosk.paired": {
      "post": {
        "summary": "kiosk.paired",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "kiosk.paired"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Kiosk"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "kiosk.revoked": {
      "post": {
        "summary": "kiosk.revoked",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "kiosk.revoked"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Kiosk"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "courier.signed_in": {
      "post": {
        "summary": "courier.signed_in",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "courier.signed_in"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Courier"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "courier.signed_out": {
      "post": {
        "summary": "courier.signed_out",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "courier.signed_out"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Courier"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "person.created": {
      "post": {
        "summary": "item.created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.created"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Item"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "person.updated": {
      "post": {
        "summary": "item.created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.created"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Item"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "person.deactivated": {
      "post": {
        "summary": "item.created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.created"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Item"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "person.deleted": {
      "post": {
        "summary": "item.created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.created"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Item"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "people.sync.completed": {
      "post": {
        "summary": "item.created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.created"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Item"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    },
    "people.sync.failed": {
      "post": {
        "summary": "item.created",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/Event"
                  },
                  {
                    "type": "object",
                    "properties": {
                      "type": {
                        "const": "item.created"
                      },
                      "data": {
                        "$ref": "#/components/schemas/Item"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx answer confirms the delivery."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "A venue key, vf_live_…, from Settings, For developers. Each operation lists the scope it needs."
      }
    },
    "schemas": {
      "Item": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The item's id (a UUID)."
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "in_care",
              "in_transit",
              "claimed",
              "expired",
              "donated",
              "disposed",
              "trash",
              "pending_witness"
            ],
            "description": "in_care means still held at the venue; in_transit means on its way to another venue of the same customer group and off the guest page."
          },
          "category": {
            "type": [
              "string",
              "null"
            ]
          },
          "found_date": {
            "type": "string",
            "format": "date"
          },
          "found_time": {
            "type": [
              "string",
              "null"
            ],
            "description": "HH:MM"
          },
          "keep_until": {
            "type": "string",
            "format": "date"
          },
          "location": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "colour": {
            "type": [
              "string",
              "null"
            ]
          },
          "brand": {
            "type": [
              "string",
              "null"
            ]
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "value_band": {
            "type": [
              "string",
              "null"
            ]
          },
          "photo_public": {
            "type": "boolean",
            "description": "Whether the photo is shown to guests."
          },
          "photo_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "Only when the photo is public."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "stay": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StaySummary"
              },
              {
                "type": "null"
              }
            ]
          },
          "transfer": {
            "type": [
              "object",
              "null"
            ],
            "description": "Set only while the item is on its way to another venue (status in_transit).",
            "properties": {
              "id": {
                "type": "integer"
              },
              "status": {
                "type": "string",
                "enum": [
                  "in_transit"
                ]
              },
              "source": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "code": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "code",
                  "name"
                ],
                "additionalProperties": false
              },
              "destination": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "id": {
                    "type": "integer"
                  },
                  "code": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  }
                },
                "required": [
                  "id",
                  "code",
                  "name"
                ],
                "additionalProperties": false
              },
              "sent_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "required": [
              "id",
              "status",
              "source",
              "destination",
              "sent_at"
            ],
            "additionalProperties": false
          },
          "custom_values": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            },
            "description": "vFound Enterprise custom attributes: your organisation's own fields for this record, by field key. Empty when none are set. Values stay here after a field is archived or the plan ends."
          },
          "checklists": {
            "type": "array",
            "description": "Completed workflow checklists, on single-record answers.",
            "items": {
              "$ref": "#/components/schemas/CompletedChecklist"
            }
          },
          "journey": {
            "type": [
              "object",
              "null"
            ],
            "maxProperties": 8,
            "additionalProperties": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 100
            },
            "description": "Private context in the named versioned schema. Null historical schema means legacy-v1. service_at requires an ISO instant with an offset. Unknown keys and non-string values are rejected."
          },
          "journey_schema": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "context": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "value": {
                  "type": "string"
                }
              },
              "required": [
                "key",
                "label",
                "value"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "id",
          "title",
          "status",
          "category",
          "found_date",
          "found_time",
          "keep_until",
          "location",
          "description",
          "colour",
          "brand",
          "tags",
          "value_band",
          "photo_public",
          "photo_url",
          "created_at",
          "updated_at",
          "stay",
          "transfer",
          "custom_values"
        ],
        "additionalProperties": false,
        "description": "A found item (vFound Lost & Found)."
      },
      "Claim": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The claim's reference."
          },
          "status": {
            "type": "string",
            "enum": [
              "unread",
              "open",
              "accepted",
              "awaiting_information",
              "ready_for_pickup",
              "ready_for_shipment",
              "shipped",
              "closed",
              "rejected",
              "expired"
            ]
          },
          "item": {
            "type": "object",
            "properties": {
              "id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "title"
            ],
            "additionalProperties": false
          },
          "claimant": {
            "type": "object",
            "properties": {
              "first_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "last_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "phone": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "first_name",
              "last_name",
              "email",
              "phone"
            ],
            "additionalProperties": false
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "place_lost": {
            "type": [
              "string",
              "null"
            ]
          },
          "date_lost": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "fr",
              "de",
              "nl",
              "it",
              "pt",
              "pl",
              "sv",
              "tr",
              "ja",
              "zh",
              "ar"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "checklists": {
            "type": "array",
            "description": "Completed workflow checklists, on single-record answers.",
            "items": {
              "$ref": "#/components/schemas/CompletedChecklist"
            }
          }
        },
        "required": [
          "id",
          "status",
          "item",
          "claimant",
          "description",
          "place_lost",
          "date_lost",
          "language",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false,
        "description": "A guest's claim for a found item."
      },
      "LostReport": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The report's reference."
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "closed"
            ]
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "category": {
            "type": [
              "string",
              "null"
            ]
          },
          "colour_brand": {
            "type": [
              "string",
              "null"
            ]
          },
          "place_lost": {
            "type": [
              "string",
              "null"
            ]
          },
          "date_lost": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "reporter": {
            "type": "object",
            "properties": {
              "first_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "last_name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "phone": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "first_name",
              "last_name",
              "email",
              "phone"
            ],
            "additionalProperties": false
          },
          "find_my_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The guest's private page for this report."
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "fr",
              "de",
              "nl",
              "it",
              "pt",
              "pl",
              "sv",
              "tr",
              "ja",
              "zh",
              "ar"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "journey": {
            "type": [
              "object",
              "null"
            ],
            "maxProperties": 8,
            "additionalProperties": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 100
            },
            "description": "Private context in the named versioned schema. Null historical schema means legacy-v1. service_at requires an ISO instant with an offset. Unknown keys and non-string values are rejected."
          },
          "journey_history": {
            "type": "array",
            "description": "Retained earlier journey values, ordered by version id and scoped to this report and venue. Erased/deleted versions are absent.",
            "items": {
              "type": "object",
              "properties": {
                "recorded_at": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "journey": {
                  "type": [
                    "object",
                    "null"
                  ],
                  "properties": {
                    "service": {
                      "type": "string",
                      "maxLength": 100
                    },
                    "departure": {
                      "type": "string",
                      "maxLength": 100
                    },
                    "seat": {
                      "type": "string",
                      "maxLength": 100
                    },
                    "event": {
                      "type": "string",
                      "maxLength": 100
                    },
                    "area": {
                      "type": "string",
                      "maxLength": 100
                    }
                  },
                  "additionalProperties": false,
                  "description": "Private optional context; retained when collection is disabled. No automatic routing or matching."
                }
              },
              "required": [
                "recorded_at",
                "journey"
              ],
              "additionalProperties": false
            }
          },
          "journey_schema": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "context": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "value": {
                  "type": "string"
                }
              },
              "required": [
                "key",
                "label",
                "value"
              ],
              "additionalProperties": false
            }
          },
          "fingerprint": {
            "type": "string",
            "description": "Current edit fingerprint in private list/edit responses only; never a guest access link."
          }
        },
        "required": [
          "id",
          "status",
          "title",
          "description",
          "category",
          "colour_brand",
          "place_lost",
          "date_lost",
          "reporter",
          "find_my_url",
          "language",
          "created_at"
        ],
        "additionalProperties": false,
        "description": "A guest's report of something they lost."
      },
      "Analytics": {
        "type": "object",
        "description": "Lost & Found figures for the period: items logged and returned, return rate, median days to return, claims, what happened to items, categories and hotspots.",
        "properties": {
          "from": {
            "type": "string",
            "format": "date"
          },
          "to": {
            "type": "string",
            "format": "date"
          },
          "logged": {
            "type": "integer"
          },
          "returned": {
            "type": "integer"
          },
          "return_rate": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Percent."
          },
          "median_days_to_return": {
            "type": [
              "number",
              "null"
            ]
          },
          "returns_completed": {
            "type": "integer"
          },
          "claims": {
            "type": "object"
          },
          "disposition": {
            "type": "object"
          },
          "categories": {
            "type": "array"
          },
          "hotspots": {
            "type": "array"
          },
          "median_hours_to_first_claim": {
            "type": [
              "number",
              "null"
            ]
          },
          "median_hours_claim_to_approval": {
            "type": [
              "number",
              "null"
            ]
          },
          "median_hours_approval_to_handover": {
            "type": [
              "number",
              "null"
            ]
          },
          "still_here_14_days": {
            "type": "integer",
            "description": "Right now: items waiting for an owner, or promised and not picked up, found 14 or more days ago."
          },
          "expiring_7_days": {
            "type": "integer",
            "description": "Right now: items waiting for an owner whose keep-until date is within the next 7 days."
          }
        },
        "additionalProperties": true
      },
      "Parcel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "waiting",
              "collected",
              "returned"
            ]
          },
          "recipient": {
            "type": "object",
            "properties": {
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "unit": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "reference": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "name",
              "email",
              "unit",
              "reference"
            ],
            "additionalProperties": false
          },
          "carrier": {
            "type": [
              "string",
              "null"
            ]
          },
          "tracking": {
            "type": [
              "string",
              "null"
            ]
          },
          "sender": {
            "type": [
              "string",
              "null"
            ]
          },
          "size": {
            "type": [
              "string",
              "null"
            ]
          },
          "shelf": {
            "type": [
              "string",
              "null"
            ]
          },
          "pickup_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "The code the recipient shows at the desk, while the parcel waits."
          },
          "notified_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "collected_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "collected_by": {
            "type": [
              "string",
              "null"
            ]
          },
          "returned_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "handling_tags": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "perishable",
                "fragile",
                "oversized",
                "signature_required",
                "high_value"
              ]
            }
          },
          "hold_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "snoozed_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "arrived_at_desk": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "escalated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "stay": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StaySummary"
              },
              {
                "type": "null"
              }
            ]
          },
          "custom_values": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            },
            "description": "vFound Enterprise custom attributes: your organisation's own fields for this record, by field key. Empty when none are set. Values stay here after a field is archived or the plan ends."
          },
          "checklists": {
            "type": "array",
            "description": "Completed workflow checklists, on single-record answers.",
            "items": {
              "$ref": "#/components/schemas/CompletedChecklist"
            }
          }
        },
        "required": [
          "id",
          "status",
          "recipient",
          "carrier",
          "tracking",
          "sender",
          "size",
          "shelf",
          "pickup_code",
          "notified_at",
          "collected_at",
          "collected_by",
          "returned_at",
          "created_at",
          "updated_at",
          "handling_tags",
          "hold_until",
          "snoozed_until",
          "arrived_at_desk",
          "escalated_at",
          "stay",
          "custom_values"
        ],
        "additionalProperties": false,
        "description": "A parcel at the desk (vFound Parcels)."
      },
      "CheckroomTicket": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "in",
              "returned",
              "left",
              "moved"
            ]
          },
          "number": {
            "type": [
              "integer",
              "null"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "coat",
              "bag",
              "luggage",
              "other"
            ]
          },
          "pieces": {
            "type": "integer"
          },
          "piece_records": {
            "type": "array",
            "description": "The individually tagged pieces on this ticket.",
            "items": {
              "$ref": "#/components/schemas/CheckroomPiece"
            }
          },
          "guest": {
            "type": "object",
            "properties": {
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "room": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "name",
              "email",
              "room"
            ],
            "additionalProperties": false
          },
          "fee": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "amount": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "In cents."
              },
              "method": {
                "type": "string",
                "enum": [
                  "cash",
                  "card"
                ]
              }
            },
            "required": [
              "amount",
              "method"
            ],
            "additionalProperties": false
          },
          "collect_by": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "For luggage: when the guest will collect it."
          },
          "checked_in_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "returned_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "without_ticket": {
            "type": "boolean",
            "description": "Handed back without the ticket, after checking who the guest is."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "currency": {
            "type": [
              "string",
              "null"
            ],
            "description": "ISO 4217 currency code."
          },
          "payment_status": {
            "type": "string",
            "enum": [
              "not_due",
              "due",
              "pending",
              "paid"
            ]
          },
          "station": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ],
            "additionalProperties": false
          },
          "event": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name"
            ],
            "additionalProperties": false
          },
          "storage_location": {
            "type": [
              "string",
              "null"
            ]
          },
          "ready_requested_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ready_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "custom_values": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            },
            "description": "vFound Enterprise custom attributes: your organisation's own fields for this record, by field key. Empty when none are set. Values stay here after a field is archived or the plan ends."
          },
          "checklists": {
            "type": "array",
            "description": "Completed workflow checklists, on single-record answers.",
            "items": {
              "$ref": "#/components/schemas/CompletedChecklist"
            }
          }
        },
        "required": [
          "id",
          "status",
          "number",
          "kind",
          "pieces",
          "piece_records",
          "guest",
          "fee",
          "collect_by",
          "checked_in_at",
          "returned_at",
          "without_ticket",
          "created_at",
          "currency",
          "payment_status",
          "station",
          "event",
          "storage_location",
          "ready_requested_at",
          "ready_at",
          "custom_values"
        ],
        "additionalProperties": false,
        "description": "A checkroom ticket for coats, bags or luggage (vFound Checkroom)."
      },
      "Loan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "checkout_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "out",
              "returned",
              "lost"
            ]
          },
          "overdue": {
            "type": "boolean"
          },
          "item": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              },
              "tag": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "code": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "name",
              "tag",
              "code"
            ],
            "additionalProperties": false
          },
          "borrower": {
            "type": "object",
            "properties": {
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "reference": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "name",
              "email",
              "reference"
            ],
            "additionalProperties": false
          },
          "lent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "due_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "returned_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "return_condition": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "good",
              "damaged",
              "incomplete",
              null
            ]
          },
          "extension_requested_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "extension_request": {
            "type": [
              "object",
              "null"
            ],
            "description": "What the borrower asked for from My vFound, until staff give more time.",
            "properties": {
              "due_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "message": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "due_at",
              "message"
            ],
            "additionalProperties": false
          },
          "problem_reported_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "problem_report": {
            "type": [
              "string",
              "null"
            ],
            "description": "The problem the borrower last reported from My vFound."
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "checklists": {
            "type": "array",
            "description": "Completed workflow checklists, on single-record answers.",
            "items": {
              "$ref": "#/components/schemas/CompletedChecklist"
            }
          }
        },
        "required": [
          "id",
          "status",
          "overdue",
          "item",
          "borrower",
          "lent_at",
          "due_at",
          "returned_at",
          "return_condition",
          "created_at",
          "updated_at",
          "checkout_id",
          "extension_requested_at",
          "extension_request",
          "problem_reported_at",
          "problem_report"
        ],
        "additionalProperties": false,
        "description": "Equipment handed out to someone (vFound Equipment)."
      },
      "EquipmentItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "owner_business_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The venue that owns the item."
          },
          "custody_business_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The venue currently holding the item, or null while it is in transit."
          },
          "service_business_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The venue responsible for service and maintenance."
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "available",
              "out",
              "repair",
              "retired",
              "transfer",
              "transit"
            ]
          },
          "category": {
            "type": [
              "string",
              "null"
            ]
          },
          "tag": {
            "type": [
              "string",
              "null"
            ],
            "description": "Your asset tag."
          },
          "code": {
            "type": [
              "string",
              "null"
            ],
            "description": "The code on its vFound label."
          },
          "label_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "The address its label's QR code holds."
          },
          "location": {
            "type": [
              "string",
              "null"
            ]
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "loan_hours": {
            "type": [
              "integer",
              "null"
            ],
            "description": "How many hours it usually goes out for."
          },
          "serial_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "replacement_value": {
            "type": [
              "string",
              "null"
            ],
            "description": "Replacement value as a decimal amount."
          },
          "purchase_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "warranty_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "custom_fields": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean",
                "null"
              ]
            }
          },
          "maintenance_due_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "stock_checked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "custom_values": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            },
            "description": "vFound Enterprise custom attributes: your organisation's own fields for this record, by field key. Empty when none are set. Values stay here after a field is archived or the plan ends."
          }
        },
        "required": [
          "id",
          "owner_business_id",
          "custody_business_id",
          "service_business_id",
          "name",
          "status",
          "category",
          "tag",
          "code",
          "label_url",
          "location",
          "notes",
          "loan_hours",
          "serial_number",
          "replacement_value",
          "purchase_date",
          "warranty_until",
          "custom_fields",
          "maintenance_due_at",
          "stock_checked_at",
          "created_at",
          "updated_at",
          "custom_values"
        ],
        "additionalProperties": false,
        "description": "A thing the desk hands out (vFound Equipment)."
      },
      "Visit": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "expected",
              "in",
              "out",
              "cancelled",
              "missed"
            ]
          },
          "visitor": {
            "type": "object",
            "properties": {
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "company": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "name",
              "email",
              "company"
            ],
            "additionalProperties": false
          },
          "host": {
            "type": "object",
            "properties": {
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "confirmed": {
                "type": "boolean"
              }
            },
            "required": [
              "name",
              "email",
              "confirmed"
            ],
            "additionalProperties": false
          },
          "purpose": {
            "type": [
              "string",
              "null"
            ]
          },
          "pass_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "The code on the visitor's pass, while expected or signed in."
          },
          "self_service": {
            "type": "boolean",
            "description": "Signed in from the venue's QR sign."
          },
          "expected_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "signed_in_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "signed_out_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "agreed_to_terms": {
            "type": "boolean"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "approval_status": {
            "type": "string",
            "enum": [
              "pending",
              "approved",
              "denied"
            ]
          },
          "type": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              },
              "kind": {
                "type": "string"
              },
              "badge_color": {
                "type": "string"
              },
              "photo_required": {
                "type": "boolean"
              },
              "identity_check_required": {
                "type": "boolean"
              }
            },
            "required": [
              "id",
              "name",
              "kind",
              "badge_color",
              "photo_required",
              "identity_check_required"
            ],
            "additionalProperties": false
          },
          "answers": {
            "type": "object",
            "additionalProperties": true
          },
          "host_reply": {
            "type": [
              "string",
              "null"
            ]
          },
          "valid_from": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "valid_until": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "recurrence": {
            "type": "string",
            "enum": [
              "once",
              "daily",
              "weekdays"
            ]
          },
          "badge_urls": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "4x3": {
                "type": "string",
                "format": "uri"
              },
              "brother": {
                "type": "string",
                "format": "uri"
              },
              "dymo": {
                "type": "string",
                "format": "uri"
              }
            },
            "required": [
              "4x3",
              "brother",
              "dymo"
            ],
            "additionalProperties": false
          },
          "has_photo": {
            "type": "boolean",
            "description": "True when the visit has a private visitor photo. The image itself is available only in the authenticated venue workspace."
          },
          "identity_checked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "When venue staff recorded a visual check of a physical photo ID. No ID image or number is stored."
          },
          "custom_values": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            },
            "description": "vFound Enterprise custom attributes: your organisation's own fields for this record, by field key. Empty when none are set. Values stay here after a field is archived or the plan ends."
          },
          "checklists": {
            "type": "array",
            "description": "Completed workflow checklists, on single-record answers.",
            "items": {
              "$ref": "#/components/schemas/CompletedChecklist"
            }
          }
        },
        "required": [
          "id",
          "status",
          "visitor",
          "host",
          "purpose",
          "pass_code",
          "self_service",
          "expected_at",
          "signed_in_at",
          "signed_out_at",
          "agreed_to_terms",
          "created_at",
          "updated_at",
          "approval_status",
          "type",
          "answers",
          "host_reply",
          "valid_from",
          "valid_until",
          "recurrence",
          "badge_urls",
          "has_photo",
          "identity_checked_at",
          "custom_values"
        ],
        "additionalProperties": false,
        "description": "A visit (vFound Visitors)."
      },
      "Person": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email"
          },
          "unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "es",
              "fr",
              "de",
              "nl",
              "it",
              "pt",
              "pl",
              "sv",
              "tr",
              "ja",
              "zh",
              "ar"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "source": {
            "type": "string",
            "enum": [
              "manual",
              "csv",
              "scim"
            ]
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "unit",
          "reference",
          "language",
          "source",
          "active",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false,
        "description": "Someone on the venue's people list, shared by Parcels, Visitors and Equipment."
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "item.created",
                "item.updated",
                "item.disposition_recorded",
                "item.match_updated",
                "item.transfer_sent",
                "item.transfer_cancelled",
                "item.transfer_received",
                "claim.created",
                "claim.status_changed",
                "claim.ownership_reviewed",
                "claim.decision_recorded",
                "claim.release_approved",
                "claim.handover_recorded",
                "lost_report.updated",
                "lost_report.closed",
                "lost_report.contact_updated",
                "lost_report.created",
                "lost_report.match_updated",
                "parcel.logged",
                "parcel.updated",
                "parcel.reminded",
                "parcel.collected",
                "parcel.returned",
                "parcel.recipient_arrived",
                "parcel.reminders_snoozed",
                "parcel.held",
                "parcel.proxy_created",
                "parcel.pickup_served",
                "parcel.escalated",
                "parcel.outgoing_logged",
                "parcel.outgoing_handed_over",
                "parcel.round_created",
                "parcel.round_delivered",
                "checkroom.checked_in",
                "checkroom.handed_back",
                "checkroom.left",
                "checkroom.self_checkin_started",
                "checkroom.ready_requested",
                "checkroom.ready",
                "checkroom.station_created",
                "checkroom.station_updated",
                "checkroom.event_created",
                "checkroom.event_updated",
                "loan.checked_out",
                "loan.due_soon",
                "loan.overdue",
                "loan.extended",
                "loan.returned",
                "loan.lost",
                "loan.checkout_created",
                "loan.self_checkout",
                "loan.kit_created",
                "loan.kit_updated",
                "loan.reservation_requested",
                "loan.reservation_created",
                "loan.reservation_approved",
                "loan.reservation_ready",
                "loan.reservation_cancelled",
                "loan.reservation_collected",
                "loan.extension_requested",
                "loan.problem_reported",
                "loan.rule_updated",
                "loan.maintenance_logged",
                "loan.maintenance_due",
                "loan.stocktake_started",
                "loan.stocktake_completed",
                "loan.items_imported",
                "loan.transfer_prepared",
                "loan.transfer_sent",
                "loan.transfer_received",
                "loan.transfer_rejected",
                "loan.transfer_cancelled",
                "loan.transfer_exception",
                "loan.transfer_lost",
                "visit.expected",
                "visit.signed_in",
                "visit.host_confirmed",
                "visit.signed_out",
                "visit.cancelled",
                "visit.approval_requested",
                "visit.approved",
                "visit.denied",
                "visit.host_replied",
                "visit.roll_call_started",
                "visit.roll_call_completed",
                "visitor_type.created",
                "visitor_type.updated",
                "visitor_type.deactivated",
                "kiosk.paired",
                "kiosk.revoked",
                "courier.signed_in",
                "courier.signed_out",
                "person.created",
                "person.updated",
                "person.deactivated",
                "person.deleted",
                "people.sync.completed",
                "people.sync.failed"
              ]
            }
          },
          "enabled": {
            "type": "boolean",
            "description": "False once paused after 15 failed deliveries in a row."
          },
          "last_delivered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "enabled",
          "last_delivered_at",
          "created_at"
        ],
        "additionalProperties": false,
        "description": "An address that receives events."
      },
      "NewWebhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "item.created",
                "item.updated",
                "item.disposition_recorded",
                "item.match_updated",
                "item.transfer_sent",
                "item.transfer_cancelled",
                "item.transfer_received",
                "claim.created",
                "claim.status_changed",
                "claim.ownership_reviewed",
                "claim.decision_recorded",
                "claim.release_approved",
                "claim.handover_recorded",
                "lost_report.updated",
                "lost_report.closed",
                "lost_report.contact_updated",
                "lost_report.created",
                "lost_report.match_updated",
                "parcel.logged",
                "parcel.updated",
                "parcel.reminded",
                "parcel.collected",
                "parcel.returned",
                "parcel.recipient_arrived",
                "parcel.reminders_snoozed",
                "parcel.held",
                "parcel.proxy_created",
                "parcel.pickup_served",
                "parcel.escalated",
                "parcel.outgoing_logged",
                "parcel.outgoing_handed_over",
                "parcel.round_created",
                "parcel.round_delivered",
                "checkroom.checked_in",
                "checkroom.handed_back",
                "checkroom.left",
                "checkroom.self_checkin_started",
                "checkroom.ready_requested",
                "checkroom.ready",
                "checkroom.station_created",
                "checkroom.station_updated",
                "checkroom.event_created",
                "checkroom.event_updated",
                "loan.checked_out",
                "loan.due_soon",
                "loan.overdue",
                "loan.extended",
                "loan.returned",
                "loan.lost",
                "loan.checkout_created",
                "loan.self_checkout",
                "loan.kit_created",
                "loan.kit_updated",
                "loan.reservation_requested",
                "loan.reservation_created",
                "loan.reservation_approved",
                "loan.reservation_ready",
                "loan.reservation_cancelled",
                "loan.reservation_collected",
                "loan.extension_requested",
                "loan.problem_reported",
                "loan.rule_updated",
                "loan.maintenance_logged",
                "loan.maintenance_due",
                "loan.stocktake_started",
                "loan.stocktake_completed",
                "loan.items_imported",
                "loan.transfer_prepared",
                "loan.transfer_sent",
                "loan.transfer_received",
                "loan.transfer_rejected",
                "loan.transfer_cancelled",
                "loan.transfer_exception",
                "loan.transfer_lost",
                "visit.expected",
                "visit.signed_in",
                "visit.host_confirmed",
                "visit.signed_out",
                "visit.cancelled",
                "visit.approval_requested",
                "visit.approved",
                "visit.denied",
                "visit.host_replied",
                "visit.roll_call_started",
                "visit.roll_call_completed",
                "visitor_type.created",
                "visitor_type.updated",
                "visitor_type.deactivated",
                "kiosk.paired",
                "kiosk.revoked",
                "courier.signed_in",
                "courier.signed_out",
                "person.created",
                "person.updated",
                "person.deactivated",
                "person.deleted",
                "people.sync.completed",
                "people.sync.failed"
              ]
            }
          },
          "enabled": {
            "type": "boolean",
            "description": "False once paused after 15 failed deliveries in a row."
          },
          "last_delivered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "secret": {
            "type": "string",
            "description": "Shown once. Signs every delivery; keep it secret."
          }
        },
        "required": [
          "id",
          "url",
          "events",
          "enabled",
          "last_delivered_at",
          "created_at",
          "secret"
        ],
        "additionalProperties": false,
        "description": "An address just subscribed, with its signing secret."
      },
      "Meta": {
        "type": "object",
        "properties": {
          "page": {
            "type": "integer"
          },
          "per_page": {
            "type": "integer"
          },
          "total": {
            "type": "integer"
          },
          "last_page": {
            "type": "integer"
          }
        },
        "required": [
          "page",
          "per_page",
          "total",
          "last_page"
        ],
        "additionalProperties": false
      },
      "Error": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          },
          "code": {
            "type": "string",
            "enum": [
              "parcel_not_waiting",
              "tracking_duplicate",
              "no_email",
              "capacity_full",
              "already_checked_in",
              "already_handed_back",
              "nothing_to_hand_back",
              "number_in_use",
              "ticket_closed",
              "item_out",
              "item_in_repair",
              "item_retired",
              "reservation_conflict",
              "already_back",
              "not_out",
              "borrower_overdue",
              "borrower_item_limit",
              "reservation_not_ready",
              "reservation_item_mismatch",
              "reservation_category_mismatch",
              "reservation_borrower_mismatch",
              "reservation_too_long",
              "reservation_daily_limit",
              "booking_notice",
              "booking_too_far_ahead",
              "desk_closed",
              "kit_unavailable",
              "stocktake_open",
              "item_unavailable",
              "transfer_open",
              "transfer_not_ready",
              "transfer_not_in_transit",
              "transfer_already_sent",
              "already_signed_in",
              "visit_closed",
              "not_signed_in",
              "not_expected",
              "approval_required",
              "visit_not_valid_today",
              "idempotency_key_invalid",
              "idempotency_key_reused",
              "idempotency_in_progress",
              "checklist_incomplete",
              "acting_user_refused",
              "acting_user_role"
            ],
            "x-enum-descriptions": [
              "The parcel is no longer waiting: it was already collected, returned or delivered.",
              "A parcel with this tracking number is already waiting here.",
              "The person or visitor has no email address, so nothing can be sent.",
              "Every checkroom number is in use.",
              "The checkroom ticket is already checked in.",
              "The checkroom ticket was already handed back.",
              "The checkroom ticket has nothing to hand back.",
              "That checkroom number is already in use.",
              "Only an open checkroom ticket can be emailed.",
              "The equipment is out with someone. Take it back first.",
              "The equipment is set aside for repair.",
              "The equipment is retired, so it cannot be handed out or reserved.",
              "Someone has reserved the item, or the last free one in its category, during this time, or it is expected to still be out.",
              "The equipment was already taken back.",
              "The equipment is not out, so it cannot get more time, a reminder or be marked as not coming back.",
              "The borrower has overdue equipment, and the venue or the category allows nothing more until it comes back.",
              "This would give the borrower more items than the venue or the category allows at once.",
              "The reservation is not approved yet, or it was already collected or cancelled.",
              "The checkout does not include the item the reservation is for.",
              "The checkout includes an item outside the reserved category.",
              "The reservation belongs to a different borrower.",
              "The reservation is longer than the category can be borrowed. Only reservations made from My vFound are limited this way.",
              "The borrower already made 5 reservations from My vFound in the last 24 hours.",
              "The reservation starts sooner than the category's minimum notice allows.",
              "The booking, checkout or new due time ends later than the category can be booked ahead.",
              "The reservation would start on a day the equipment desk is closed.",
              "Part of a kit or cart is not available for this time, so nothing was reserved. The unavailable field lists each part and why.",
              "A stock-take is already open. Finish it first.",
              "The equipment is not available or set aside for repair, so it cannot start a transfer.",
              "The equipment already has an open transfer.",
              "Only a prepared transfer can be sent.",
              "Only equipment in transit can be received or marked with a problem.",
              "A sent transfer can no longer be cancelled or rejected.",
              "The visitor is already signed in.",
              "The visit is closed. Sign the visitor in as a new visit.",
              "The visitor is not signed in.",
              "Only an expected visit can be cancelled or sent a pass.",
              "The visit needs approval before the visitor can sign in.",
              "The pass cannot be used again today, or today is outside its dates.",
              "400: the Idempotency-Key header is not 1 to 191 visible ASCII characters.",
              "422: this Idempotency-Key was already used for a different request.",
              "409: the first request with this Idempotency-Key is still running. Try again shortly.",
              "422: a workflow checklist applies to this step and its required steps are not confirmed. The checklist field lists what is missing.",
              "403: X-Acting-User does not name exactly one active team member of this venue, or the key is a connection made by signing in.",
              "403: the team member named in X-Acting-User cannot use this operation's scope with their role at the venue."
            ],
            "description": "A machine-readable reason. A conflict answers 422 with one of the first codes; the last three come from the Idempotency-Key header.\n- `parcel_not_waiting`: The parcel is no longer waiting: it was already collected, returned or delivered.\n- `tracking_duplicate`: A parcel with this tracking number is already waiting here.\n- `no_email`: The person or visitor has no email address, so nothing can be sent.\n- `capacity_full`: Every checkroom number is in use.\n- `already_checked_in`: The checkroom ticket is already checked in.\n- `already_handed_back`: The checkroom ticket was already handed back.\n- `nothing_to_hand_back`: The checkroom ticket has nothing to hand back.\n- `number_in_use`: That checkroom number is already in use.\n- `ticket_closed`: Only an open checkroom ticket can be emailed.\n- `item_out`: The equipment is out with someone. Take it back first.\n- `item_in_repair`: The equipment is set aside for repair.\n- `item_retired`: The equipment is retired, so it cannot be handed out or reserved.\n- `reservation_conflict`: Someone has reserved the item, or the last free one in its category, during this time, or it is expected to still be out.\n- `already_back`: The equipment was already taken back.\n- `not_out`: The equipment is not out, so it cannot get more time, a reminder or be marked as not coming back.\n- `borrower_overdue`: The borrower has overdue equipment, and the venue or the category allows nothing more until it comes back.\n- `borrower_item_limit`: This would give the borrower more items than the venue or the category allows at once.\n- `reservation_not_ready`: The reservation is not approved yet, or it was already collected or cancelled.\n- `reservation_item_mismatch`: The checkout does not include the item the reservation is for.\n- `reservation_category_mismatch`: The checkout includes an item outside the reserved category.\n- `reservation_borrower_mismatch`: The reservation belongs to a different borrower.\n- `reservation_too_long`: The reservation is longer than the category can be borrowed. Only reservations made from My vFound are limited this way.\n- `reservation_daily_limit`: The borrower already made 5 reservations from My vFound in the last 24 hours.\n- `booking_notice`: The reservation starts sooner than the category's minimum notice allows.\n- `booking_too_far_ahead`: The booking, checkout or new due time ends later than the category can be booked ahead.\n- `desk_closed`: The reservation would start on a day the equipment desk is closed.\n- `kit_unavailable`: Part of a kit or cart is not available for this time, so nothing was reserved. The unavailable field lists each part and why.\n- `stocktake_open`: A stock-take is already open. Finish it first.\n- `item_unavailable`: The equipment is not available or set aside for repair, so it cannot start a transfer.\n- `transfer_open`: The equipment already has an open transfer.\n- `transfer_not_ready`: Only a prepared transfer can be sent.\n- `transfer_not_in_transit`: Only equipment in transit can be received or marked with a problem.\n- `transfer_already_sent`: A sent transfer can no longer be cancelled or rejected.\n- `already_signed_in`: The visitor is already signed in.\n- `visit_closed`: The visit is closed. Sign the visitor in as a new visit.\n- `not_signed_in`: The visitor is not signed in.\n- `not_expected`: Only an expected visit can be cancelled or sent a pass.\n- `approval_required`: The visit needs approval before the visitor can sign in.\n- `visit_not_valid_today`: The pass cannot be used again today, or today is outside its dates.\n- `idempotency_key_invalid`: 400: the Idempotency-Key header is not 1 to 191 visible ASCII characters.\n- `idempotency_key_reused`: 422: this Idempotency-Key was already used for a different request.\n- `idempotency_in_progress`: 409: the first request with this Idempotency-Key is still running. Try again shortly.\n- `checklist_incomplete`: 422: a workflow checklist applies to this step and its required steps are not confirmed. The checklist field lists what is missing.\n- `acting_user_refused`: 403: X-Acting-User does not name exactly one active team member of this venue, or the key is a connection made by signing in.\n- `acting_user_role`: 403: the team member named in X-Acting-User cannot use this operation's scope with their role at the venue."
          },
          "errors": {
            "type": "object",
            "additionalProperties": {
              "type": "array",
              "items": {
                "type": "string"
              }
            }
          },
          "checklist": {
            "type": "object",
            "description": "With checklist_incomplete: the checklist's name and the labels of the steps still to confirm.",
            "properties": {
              "name": {
                "type": "string"
              },
              "missing": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "unavailable": {
            "type": "array",
            "description": "With kit_unavailable: each part that could not be reserved, how many, and why.",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                },
                "reason": {
                  "type": "string"
                },
                "loan_item_id": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "category": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "reason_template": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The reason as a template with {0}-style places, when the reason has values."
                },
                "reason_values": {
                  "type": [
                    "array",
                    "null"
                  ],
                  "description": "Values for reason_template: text, a number, a time as {datetime, zone}, a day as {date}, or a fixed phrase as {t}."
                }
              },
              "required": [
                "name",
                "count",
                "reason",
                "loan_item_id",
                "category",
                "reason_template",
                "reason_values"
              ],
              "additionalProperties": false
            }
          },
          "message_template": {
            "type": "string",
            "description": "With some Equipment refusals: the message as a template with {0}-style places, so a client can show it in its own language."
          },
          "message_values": {
            "type": "array",
            "description": "Values for message_template: text, a number, a time as {datetime, zone}, a day as {date}, a fixed phrase as {t}, or {unavailable: true} for the list in unavailable."
          }
        },
        "required": [
          "message"
        ]
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Starts with evt_. The same id is sent again when a delivery is resent."
          },
          "type": {
            "type": "string",
            "enum": [
              "item.created",
              "item.updated",
              "item.disposition_recorded",
              "item.match_updated",
              "item.transfer_sent",
              "item.transfer_cancelled",
              "item.transfer_received",
              "claim.created",
              "claim.status_changed",
              "claim.ownership_reviewed",
              "claim.decision_recorded",
              "claim.release_approved",
              "claim.handover_recorded",
              "lost_report.updated",
              "lost_report.closed",
              "lost_report.contact_updated",
              "lost_report.created",
              "lost_report.match_updated",
              "parcel.logged",
              "parcel.updated",
              "parcel.reminded",
              "parcel.collected",
              "parcel.returned",
              "parcel.recipient_arrived",
              "parcel.reminders_snoozed",
              "parcel.held",
              "parcel.proxy_created",
              "parcel.pickup_served",
              "parcel.escalated",
              "parcel.outgoing_logged",
              "parcel.outgoing_handed_over",
              "parcel.round_created",
              "parcel.round_delivered",
              "checkroom.checked_in",
              "checkroom.handed_back",
              "checkroom.left",
              "checkroom.self_checkin_started",
              "checkroom.ready_requested",
              "checkroom.ready",
              "checkroom.station_created",
              "checkroom.station_updated",
              "checkroom.event_created",
              "checkroom.event_updated",
              "loan.checked_out",
              "loan.due_soon",
              "loan.overdue",
              "loan.extended",
              "loan.returned",
              "loan.lost",
              "loan.checkout_created",
              "loan.self_checkout",
              "loan.kit_created",
              "loan.kit_updated",
              "loan.reservation_requested",
              "loan.reservation_created",
              "loan.reservation_approved",
              "loan.reservation_ready",
              "loan.reservation_cancelled",
              "loan.reservation_collected",
              "loan.extension_requested",
              "loan.problem_reported",
              "loan.rule_updated",
              "loan.maintenance_logged",
              "loan.maintenance_due",
              "loan.stocktake_started",
              "loan.stocktake_completed",
              "loan.items_imported",
              "loan.transfer_prepared",
              "loan.transfer_sent",
              "loan.transfer_received",
              "loan.transfer_rejected",
              "loan.transfer_cancelled",
              "loan.transfer_exception",
              "loan.transfer_lost",
              "visit.expected",
              "visit.signed_in",
              "visit.host_confirmed",
              "visit.signed_out",
              "visit.cancelled",
              "visit.approval_requested",
              "visit.approved",
              "visit.denied",
              "visit.host_replied",
              "visit.roll_call_started",
              "visit.roll_call_completed",
              "visitor_type.created",
              "visitor_type.updated",
              "visitor_type.deactivated",
              "kiosk.paired",
              "kiosk.revoked",
              "courier.signed_in",
              "courier.signed_out",
              "person.created",
              "person.updated",
              "person.deactivated",
              "person.deleted",
              "people.sync.completed",
              "people.sync.failed"
            ]
          },
          "created": {
            "type": "string",
            "format": "date-time"
          },
          "venue": {
            "type": "object",
            "properties": {
              "code": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "code",
              "name"
            ],
            "additionalProperties": false
          },
          "data": {
            "type": "object",
            "description": "The record, in the same shape as the API returns it."
          }
        },
        "required": [
          "id",
          "type",
          "created",
          "venue",
          "data"
        ],
        "additionalProperties": false
      },
      "VisitorType": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "guest",
              "interview",
              "contractor",
              "delivery",
              "custom"
            ]
          },
          "questions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "required": {
                  "type": "boolean"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "text",
                    "dropdown",
                    "checkbox",
                    "date"
                  ],
                  "default": "text"
                },
                "options": {
                  "type": "array",
                  "maxItems": 30,
                  "items": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "description": "Required non-empty choices for dropdown questions."
                }
              },
              "required": [
                "key",
                "label",
                "required"
              ],
              "additionalProperties": false
            }
          },
          "terms": {
            "type": [
              "string",
              "null"
            ]
          },
          "badge_color": {
            "type": "string"
          },
          "approval_required": {
            "type": "boolean"
          },
          "retention_days": {
            "type": [
              "integer",
              "null"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "photo_required": {
            "type": "boolean",
            "description": "Require a private visitor photo before sign-in."
          },
          "identity_check_required": {
            "type": "boolean",
            "description": "Require venue staff to record a visual check of a physical photo ID before sign-in."
          }
        },
        "required": [
          "id",
          "name",
          "kind",
          "questions",
          "terms",
          "badge_color",
          "approval_required",
          "retention_days",
          "active",
          "created_at",
          "updated_at",
          "photo_required",
          "identity_check_required"
        ],
        "additionalProperties": false,
        "description": "One configurable visitor type at this venue."
      },
      "Kiosk": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "paired_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_seen_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "waiting": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "name",
          "paired_at",
          "last_seen_at",
          "revoked_at",
          "waiting"
        ],
        "additionalProperties": false
      },
      "KioskPairing": {
        "type": "object",
        "properties": {
          "device_id": {
            "type": "integer"
          },
          "code": {
            "type": "string"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "pair_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "device_id",
          "code",
          "expires_at",
          "pair_url"
        ],
        "additionalProperties": false
      },
      "RollCallEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "business_id": {
            "type": "integer"
          },
          "roll_call_id": {
            "type": "integer"
          },
          "visit_id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "safe",
              "missing"
            ]
          },
          "marked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "marked_by": {
            "type": [
              "integer",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "visit": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "id",
          "business_id",
          "roll_call_id",
          "visit_id",
          "status",
          "marked_at",
          "marked_by",
          "created_at",
          "updated_at",
          "visit"
        ],
        "additionalProperties": false
      },
      "RollCall": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "business_id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "complete"
            ]
          },
          "include_expected": {
            "type": "boolean"
          },
          "started_by": {
            "type": [
              "integer",
              "null"
            ]
          },
          "ended_by": {
            "type": [
              "integer",
              "null"
            ]
          },
          "ended_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "entries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RollCallEntry"
            }
          },
          "counts": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer"
              },
              "safe": {
                "type": "integer"
              },
              "missing": {
                "type": "integer"
              }
            },
            "required": [
              "total",
              "safe",
              "missing"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "id",
          "business_id",
          "status",
          "include_expected",
          "started_by",
          "ended_by",
          "ended_at",
          "created_at",
          "updated_at",
          "entries",
          "counts"
        ],
        "additionalProperties": false
      },
      "Courier": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "visit_id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "company": {
            "type": [
              "string",
              "null"
            ]
          },
          "signed_in_at": {
            "type": "string",
            "format": "date-time"
          },
          "signed_out_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "visit_id",
          "name",
          "company",
          "signed_in_at",
          "signed_out_at"
        ],
        "additionalProperties": false
      },
      "VisitorAnalytics": {
        "type": "object",
        "properties": {
          "period_days": {
            "type": "integer"
          },
          "visits": {
            "type": "integer"
          },
          "by_day": {
            "type": "object",
            "additionalProperties": true
          },
          "by_hour": {
            "type": "object",
            "additionalProperties": true
          },
          "by_type": {
            "type": "object",
            "additionalProperties": true
          },
          "by_host": {
            "type": "object",
            "additionalProperties": true
          },
          "average_stay_minutes": {
            "type": [
              "integer",
              "null"
            ]
          },
          "from": {
            "type": "string",
            "format": "date"
          },
          "to": {
            "type": "string",
            "format": "date"
          },
          "counted_visits": {
            "type": "integer",
            "description": "Visits in the period, not counting cancelled or missed ones."
          },
          "cancelled": {
            "type": "integer"
          },
          "missed": {
            "type": "integer"
          },
          "no_show_rate": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Percent: missed / (missed + booked visits that signed in)."
          },
          "median_host_response_minutes": {
            "type": [
              "number",
              "null"
            ]
          },
          "median_approval_minutes": {
            "type": [
              "number",
              "null"
            ]
          },
          "arrivals": {
            "type": "object",
            "properties": {
              "walk_in": {
                "type": "integer"
              },
              "invited": {
                "type": "integer"
              },
              "self_registered": {
                "type": "integer"
              }
            },
            "additionalProperties": false
          },
          "auto_sign_out_share": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Percent of signed-out visits signed out automatically."
          },
          "counted_by_day": {
            "type": "object",
            "additionalProperties": true
          },
          "counted_by_hour": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "24 counts, midnight first."
          },
          "by_weekday": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "7 counts, Monday first."
          },
          "peak_weekday": {
            "type": [
              "integer",
              "null"
            ],
            "description": "1 is Monday."
          },
          "peak_hour": {
            "type": [
              "integer",
              "null"
            ]
          },
          "trend": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "period_days",
          "visits",
          "by_day",
          "by_hour",
          "by_type",
          "by_host",
          "average_stay_minutes"
        ],
        "additionalProperties": false,
        "description": "period_days, visits, by_day, by_hour, by_type, by_host and average_stay_minutes count every visit booked in the period, any status. The other figures count visits by the day they happened (signed in, else expected, else booked) and leave out cancelled and missed visits."
      },
      "VisitorRegistration": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "enabled",
          "url"
        ],
        "additionalProperties": false
      },
      "EquipmentCheckout": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "out",
              "partial",
              "returned"
            ]
          },
          "borrower": {
            "type": "object",
            "properties": {
              "id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "reference": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "name",
              "email",
              "reference"
            ],
            "additionalProperties": false
          },
          "due_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "kit_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "reservation_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Loan"
            }
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "status",
          "borrower",
          "due_at",
          "kit_id",
          "reservation_id",
          "items",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      },
      "EquipmentKit": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "active": {
            "type": "boolean"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EquipmentItem"
            }
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "notes",
          "active",
          "items",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      },
      "EquipmentReservation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "approved",
              "ready",
              "collected",
              "cancelled"
            ]
          },
          "item": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/EquipmentItem"
              },
              {
                "type": "null"
              }
            ]
          },
          "category": {
            "type": [
              "string",
              "null"
            ]
          },
          "borrower": {
            "type": "object",
            "properties": {
              "id": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "email"
              },
              "reference": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "name",
              "email",
              "reference"
            ],
            "additionalProperties": false
          },
          "starts_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ends_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "locale": {
            "type": [
              "string",
              "null"
            ]
          },
          "group_id": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Set when the reservation is one part of a kit or cart booked as one (POST /loans/reservation-groups). Approving, cancelling or collecting any part acts on every open part."
          },
          "buffer_before_minutes": {
            "type": "integer",
            "description": "Turnaround time kept free before this booking, as the category rule was when it was made. 0 when none."
          },
          "buffer_after_minutes": {
            "type": "integer",
            "description": "Turnaround time kept free after this booking, as the category rule was when it was made. 0 when none."
          }
        },
        "required": [
          "id",
          "status",
          "item",
          "category",
          "borrower",
          "starts_at",
          "ends_at",
          "note",
          "created_at",
          "updated_at",
          "group_id",
          "buffer_before_minutes",
          "buffer_after_minutes"
        ],
        "additionalProperties": false
      },
      "EquipmentRule": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "category": {
            "type": "string"
          },
          "loan_hours": {
            "type": [
              "integer",
              "null"
            ]
          },
          "max_items": {
            "type": [
              "integer",
              "null"
            ]
          },
          "approval_required": {
            "type": "boolean"
          },
          "block_when_overdue": {
            "type": "boolean"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "buffer_before_minutes": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Minutes kept free before each new booking in this category. Null is off."
          },
          "buffer_after_minutes": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Minutes kept free after each new booking or checkout in this category. Null is off."
          },
          "notice_minutes": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Minimum notice for a new reservation, in minutes. Null is off. A checkout is the handover itself, so it does not apply to one."
          },
          "advance_days": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Nothing in this category can be booked, handed out or extended to end more than this many days from now. Null is off."
          }
        },
        "required": [
          "id",
          "category",
          "loan_hours",
          "max_items",
          "approval_required",
          "block_when_overdue",
          "created_at",
          "updated_at",
          "buffer_before_minutes",
          "buffer_after_minutes",
          "notice_minutes",
          "advance_days"
        ],
        "additionalProperties": false
      },
      "EquipmentMaintenance": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "kind": {
            "type": "string",
            "enum": [
              "service",
              "inspection",
              "repair",
              "note"
            ]
          },
          "note": {
            "type": "string"
          },
          "item": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/EquipmentItem"
              },
              {
                "type": "null"
              }
            ]
          },
          "serviced_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "due_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "kind",
          "note",
          "item",
          "serviced_at",
          "due_at",
          "completed_at",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      },
      "EquipmentStocktake": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "completed"
            ]
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expected": {
            "type": "integer"
          },
          "scanned": {
            "type": "integer"
          },
          "missing": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "name": {
                  "type": "string"
                },
                "tag": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "code": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "id",
                "name",
                "tag",
                "code"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "id",
          "name",
          "status",
          "completed_at",
          "created_at",
          "updated_at",
          "expected",
          "scanned",
          "missing"
        ],
        "additionalProperties": false
      },
      "HotelStay": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "source": {
            "type": "string",
            "enum": [
              "manual",
              "import",
              "api"
            ]
          },
          "external_stay_ref": {
            "type": "string"
          },
          "external_guest_ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "guest_name": {
            "type": "string"
          },
          "arrival_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "departure_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "source_timezone": {
            "type": "string"
          },
          "current_room": {
            "type": [
              "string",
              "null"
            ]
          },
          "stay_state": {
            "type": "string",
            "enum": [
              "expected",
              "in_house",
              "departed",
              "cancelled",
              "unknown"
            ]
          },
          "source_updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_synced_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "source_stale": {
            "type": "boolean"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "history": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "required": [
          "id",
          "source",
          "external_stay_ref",
          "external_guest_ref",
          "guest_name",
          "arrival_at",
          "departure_at",
          "source_timezone",
          "current_room",
          "stay_state",
          "source_updated_at",
          "last_synced_at",
          "source_stale",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false,
        "description": "Minimal private stay context. It excludes rates, payment, loyalty, identity documents, preferences and unrelated reservation notes."
      },
      "StaySummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "source": {
            "type": "string",
            "enum": [
              "manual",
              "import",
              "api"
            ]
          },
          "external_stay_ref": {
            "type": "string"
          },
          "external_guest_ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "guest_name": {
            "type": "string"
          },
          "current_room": {
            "type": [
              "string",
              "null"
            ]
          },
          "stay_state": {
            "type": "string",
            "enum": [
              "expected",
              "in_house",
              "departed",
              "cancelled",
              "unknown"
            ]
          },
          "source_updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_synced_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "source_stale": {
            "type": "boolean"
          },
          "room_at_event": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "source",
          "external_stay_ref",
          "external_guest_ref",
          "guest_name",
          "current_room",
          "stay_state",
          "source_updated_at",
          "last_synced_at",
          "source_stale",
          "room_at_event"
        ],
        "additionalProperties": false,
        "description": "The linked stay plus the immutable room captured when the operational record was made."
      },
      "CheckroomPiece": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "position": {
            "type": "integer",
            "minimum": 1
          },
          "tag": {
            "type": "string",
            "description": "The printable ticket number and piece letter, such as 12-A."
          },
          "kind": {
            "type": "string",
            "enum": [
              "coat",
              "bag",
              "luggage",
              "other"
            ]
          },
          "storage_location": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "in",
              "returned",
              "left",
              "moved"
            ]
          },
          "returned_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "return": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "returned_to": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "without_ticket": {
                "type": "boolean"
              },
              "has_signature": {
                "type": "boolean"
              }
            },
            "required": [
              "returned_to",
              "without_ticket",
              "has_signature"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "id",
          "position",
          "tag",
          "kind",
          "storage_location",
          "status",
          "returned_at",
          "return"
        ],
        "additionalProperties": false
      },
      "EquipmentTransfer": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "in_transit",
              "exception",
              "received",
              "rejected",
              "cancelled",
              "lost"
            ]
          },
          "item": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              },
              "tag": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "serial_number": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "status": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "tag",
              "serial_number",
              "status"
            ],
            "additionalProperties": false
          },
          "owner": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "code"
            ],
            "additionalProperties": false
          },
          "source": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "code"
            ],
            "additionalProperties": false
          },
          "destination": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "code"
            ],
            "additionalProperties": false
          },
          "service_venue": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string"
              },
              "code": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "name",
              "code"
            ],
            "additionalProperties": false
          },
          "source_location": {
            "type": [
              "string",
              "null"
            ]
          },
          "destination_location": {
            "type": "string"
          },
          "source_code": {
            "type": "string"
          },
          "destination_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "exception_note": {
            "type": [
              "string",
              "null"
            ]
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "received_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "direction": {
            "type": "string",
            "enum": [
              "incoming",
              "outgoing"
            ]
          },
          "actions": {
            "type": "object",
            "properties": {
              "send": {
                "type": "boolean"
              },
              "cancel": {
                "type": "boolean"
              },
              "reject": {
                "type": "boolean"
              },
              "receive": {
                "type": "boolean"
              },
              "exception": {
                "type": "boolean"
              },
              "lost": {
                "type": "boolean"
              }
            },
            "required": [
              "send",
              "cancel",
              "reject",
              "receive",
              "exception",
              "lost"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "id",
          "status",
          "item",
          "owner",
          "source",
          "destination",
          "service_venue",
          "source_location",
          "destination_location",
          "source_code",
          "destination_code",
          "note",
          "exception_note",
          "sent_at",
          "received_at",
          "created_at",
          "direction",
          "actions"
        ],
        "additionalProperties": false
      },
      "ItemTransfer": {
        "type": "object",
        "description": "A found item moving between two venues of one customer group, as the venue asking sees it. The sending venue dispatches it (an owner or manager), the receiving venue receives it into one of its storage bins (anyone there who logs items), or the sender cancels it before receipt.",
        "properties": {
          "id": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "in_transit",
              "received",
              "cancelled"
            ]
          },
          "direction": {
            "type": "string",
            "enum": [
              "outgoing",
              "incoming"
            ]
          },
          "item": {
            "type": "object",
            "properties": {
              "id": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uuid"
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "id",
              "title"
            ],
            "additionalProperties": false
          },
          "source": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "code": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "code",
              "name"
            ],
            "additionalProperties": false
          },
          "destination": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "integer"
              },
              "code": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "code",
              "name"
            ],
            "additionalProperties": false
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "location": {
            "type": [
              "string",
              "null"
            ],
            "description": "Where it is kept at the receiving venue, once received."
          },
          "bin": {
            "type": [
              "string",
              "null"
            ],
            "description": "The receiving venue's storage bin code, once received."
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "received_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "cancelled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "status",
          "direction",
          "item",
          "source",
          "destination",
          "note",
          "location",
          "bin",
          "sent_at",
          "received_at",
          "cancelled_at"
        ],
        "additionalProperties": false
      },
      "MatchVerdict": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "enum": [
              "strong",
              "possible",
              "unlikely"
            ]
          },
          "reason": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "cached_ai",
              "keyword"
            ]
          }
        },
        "required": [
          "label",
          "reason",
          "source"
        ],
        "additionalProperties": false
      },
      "ReportMatch": {
        "type": "object",
        "properties": {
          "item": {
            "$ref": "#/components/schemas/Item"
          },
          "match": {
            "$ref": "#/components/schemas/MatchVerdict"
          }
        },
        "required": [
          "item",
          "match"
        ],
        "additionalProperties": false
      },
      "ItemMatch": {
        "type": "object",
        "properties": {
          "report": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "title": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "title"
            ],
            "additionalProperties": false
          },
          "match": {
            "$ref": "#/components/schemas/MatchVerdict"
          }
        },
        "required": [
          "report",
          "match"
        ],
        "additionalProperties": false
      },
      "OwnershipReview": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "verified": {
            "type": "boolean"
          },
          "method": {
            "type": "string",
            "enum": [
              "distinctive_details",
              "purchase_proof",
              "staff_review"
            ]
          },
          "actor_id": {
            "type": "integer"
          },
          "created_at": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "verified",
          "method",
          "actor_id",
          "created_at"
        ],
        "additionalProperties": false
      },
      "ClaimCustody": {
        "type": "object",
        "properties": {
          "claim_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "release_approved_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "release_approved_by": {
            "type": [
              "integer",
              "null"
            ]
          },
          "handover_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "handover_at": {
            "type": [
              "string",
              "null"
            ]
          },
          "signature_recorded": {
            "type": "boolean"
          },
          "history": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer"
                },
                "type": {
                  "type": "string"
                },
                "actor_id": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "changes": {
                  "type": [
                    "array",
                    "null"
                  ],
                  "items": {
                    "type": "object",
                    "properties": {
                      "field": {
                        "type": "string"
                      },
                      "from": {
                        "type": "string"
                      },
                      "to": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "field",
                      "from",
                      "to"
                    ],
                    "additionalProperties": false
                  }
                },
                "created_at": {
                  "type": "string"
                }
              },
              "required": [
                "id",
                "type",
                "actor_id",
                "changes",
                "created_at"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "claim_id",
          "status",
          "release_approved_at",
          "release_approved_by",
          "handover_name",
          "handover_at",
          "signature_recorded",
          "history"
        ],
        "additionalProperties": false
      },
      "ItemDisposition": {
        "type": "object",
        "properties": {
          "item": {
            "$ref": "#/components/schemas/Item"
          },
          "batch_id": {
            "type": "integer"
          },
          "number": {
            "type": "integer"
          },
          "kind": {
            "type": "string",
            "enum": [
              "donated",
              "disposed"
            ]
          }
        },
        "required": [
          "item",
          "batch_id",
          "number",
          "kind"
        ],
        "additionalProperties": false
      },
      "ChecklistAnswers": {
        "type": "array",
        "maxItems": 12,
        "description": "Answers to a vFound Enterprise workflow checklist, when one applies to this step (Settings, Workflow checklists). Send each step's key: a tick step with done true, a note step with its note (up to 500 characters). An object of key to true or note text is accepted too. Without the required steps the request is refused with 422 and the code checklist_incomplete, and nothing changes. When no checklist applies, this field is ignored.",
        "items": {
          "type": "object",
          "properties": {
            "key": {
              "type": "string",
              "maxLength": 40
            },
            "done": {
              "type": "boolean"
            },
            "note": {
              "type": [
                "string",
                "null"
              ],
              "maxLength": 500
            }
          },
          "required": [
            "key"
          ],
          "additionalProperties": false
        }
      },
      "CompletedChecklist": {
        "type": "object",
        "description": "A workflow checklist completed at one step of this record: who confirmed which steps, and when.",
        "properties": {
          "stage": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "steps": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "done": {
                  "type": "boolean"
                },
                "note": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "key",
                "label",
                "done",
                "note"
              ],
              "additionalProperties": false
            }
          },
          "completed_by": {
            "type": [
              "string",
              "null"
            ]
          },
          "completed_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "stage",
          "name",
          "steps",
          "completed_by",
          "completed_at"
        ],
        "additionalProperties": false
      },
      "LostFoundDeskSettings": {
        "type": "object",
        "properties": {
          "industry": {
            "type": "string",
            "enum": [
              "none",
              "airport",
              "transit",
              "event",
              "hotel",
              "campus",
              "hospital",
              "mall",
              "attraction"
            ]
          },
          "progress_days": {
            "type": "integer",
            "enum": [
              0,
              3,
              7,
              14
            ]
          },
          "ended_email": {
            "type": "boolean"
          },
          "journey_schema": {
            "type": "string",
            "default": "legacy-v1",
            "description": "Optional in PUT. Omission preserves the current selection; industry never changes it."
          }
        },
        "required": [
          "industry",
          "progress_days",
          "ended_email"
        ],
        "additionalProperties": false
      },
      "CheckroomDeskSettings": {
        "type": "object",
        "properties": {
          "reminder_minutes": {
            "type": "integer",
            "enum": [
              0,
              15,
              30,
              60,
              120
            ]
          },
          "collection_receipts": {
            "type": "boolean"
          }
        },
        "required": [
          "reminder_minutes",
          "collection_receipts"
        ],
        "additionalProperties": false
      },
      "LfCountSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "finished_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "bin_id": {
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "created_at",
          "finished_at",
          "bin_id"
        ],
        "additionalProperties": false
      },
      "LfCountItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "bin_id": {
            "type": [
              "integer",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "title",
          "status",
          "bin_id"
        ],
        "additionalProperties": false
      },
      "LfCountResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "finished_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expected_count": {
            "type": "integer",
            "minimum": 0
          },
          "observed_count": {
            "type": "integer",
            "minimum": 0
          },
          "unrecognised": {
            "type": "integer",
            "minimum": 0
          },
          "missing": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LfCountItem"
            }
          },
          "unexpected": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LfCountItem"
            }
          },
          "no_longer_here": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "id",
          "created_at",
          "finished_at",
          "expected_count",
          "observed_count",
          "unrecognised",
          "missing",
          "unexpected",
          "no_longer_here"
        ],
        "additionalProperties": false,
        "description": "Snapshot comparison only. Item IDs in this report are workspace integers, not public item UUIDs. No custody/status mutations. Cross-venue item details are omitted."
      },
      "LfWorkQueue": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "name": {
            "type": "string",
            "maxLength": 80
          },
          "preset": {
            "type": "string",
            "enum": [
              "unreviewed",
              "awaiting_guest",
              "expiring",
              "transfer_awaiting_receipt"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "preset",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      },
      "LfQueueResult": {
        "type": "object",
        "properties": {
          "route": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "integer",
                  "minimum": 1
                },
                "title": {
                  "type": "string"
                },
                "uuid": {
                  "type": "string"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                },
                "status": {
                  "type": "string"
                },
                "expiry_date": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "route": {
                  "type": "string"
                }
              },
              "required": [
                "id"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "route",
          "items"
        ],
        "additionalProperties": false,
        "description": "At most 100 current rows, private to the key creator in this venue. Claims use id/uuid/created_at; inventory uses id/title/status/expiry_date; incoming transfers use id/title/route."
      },
      "CheckroomTemplate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "name": {
            "type": "string",
            "maxLength": 80
          },
          "configuration": {
            "type": "object",
            "properties": {
              "expected_volume": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "stations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "type": "string",
                      "maxLength": 80
                    },
                    "number_start": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 9999
                    },
                    "number_end": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 9999
                    },
                    "storage_locations": {
                      "type": [
                        "array",
                        "null"
                      ],
                      "items": {
                        "type": "string",
                        "maxLength": 100
                      },
                      "maxItems": 100
                    },
                    "piece_capacity": {
                      "type": [
                        "integer",
                        "null"
                      ],
                      "minimum": 1,
                      "maximum": 100000
                    },
                    "location_capacities": {
                      "type": [
                        "object",
                        "array",
                        "null"
                      ],
                      "additionalProperties": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 100000
                      },
                      "maxProperties": 100,
                      "propertyNames": {
                        "minLength": 1,
                        "maxLength": 100
                      }
                    }
                  },
                  "required": [
                    "name",
                    "number_start",
                    "number_end",
                    "storage_locations",
                    "piece_capacity",
                    "location_capacities"
                  ],
                  "additionalProperties": false
                }
              }
            },
            "required": [
              "expected_volume",
              "stations"
            ],
            "additionalProperties": false
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "configuration",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      },
      "CheckroomTemplateEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "minimum": 1
          },
          "name": {
            "type": "string"
          },
          "starts_at": {
            "type": "string",
            "format": "date-time"
          },
          "ends_at": {
            "type": "string",
            "format": "date-time"
          },
          "expected_volume": {
            "type": [
              "integer",
              "null"
            ]
          },
          "station_ids": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "starts_at",
          "ends_at",
          "expected_volume",
          "station_ids",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": true
      },
      "EquipmentClosure": {
        "type": "object",
        "description": "Whole days the equipment desk is closed, in the venue's time zone, both ends included. A new reservation cannot start on one; an end, due time or new due time on one moves to the next open day. Bookings made before the closure keep their times.",
        "properties": {
          "id": {
            "type": "integer"
          },
          "starts_on": {
            "type": "string",
            "format": "date"
          },
          "ends_on": {
            "type": "string",
            "format": "date"
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "description": "Internal staff note; excluded from borrower projections."
          },
          "public_message": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 300,
            "description": "Separately authored message shown to borrowers. Existing internal notes are never copied."
          }
        },
        "required": [
          "id",
          "starts_on",
          "ends_on",
          "note",
          "public_message"
        ],
        "additionalProperties": false
      },
      "EquipmentReservationGroup": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "kit_id": {
            "type": [
              "integer",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "reservations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EquipmentReservation"
            }
          }
        },
        "required": [
          "id",
          "kit_id",
          "name",
          "reservations"
        ],
        "additionalProperties": false
      },
      "LostFoundContextSchema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "fields": {
            "type": "array",
            "maxItems": 8,
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "text",
                    "instant"
                  ]
                },
                "max_length": {
                  "type": "integer",
                  "const": 100
                }
              },
              "required": [
                "key",
                "label",
                "type",
                "max_length"
              ],
              "additionalProperties": false
            }
          },
          "timezone": {
            "type": "string",
            "description": "Receiving venue time zone for optional service instants; submitted values retain an explicit offset."
          }
        },
        "required": [
          "id",
          "enabled",
          "fields"
        ],
        "additionalProperties": false
      },
      "CrmEventProjection": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schema",
          "external_key",
          "reference",
          "record_type",
          "revision",
          "occurred_at",
          "status",
          "venue_code",
          "staff_url"
        ],
        "properties": {
          "schema": {
            "type": "string",
            "const": "crm-v1"
          },
          "external_key": {
            "type": "string",
            "description": "Immutable public venue code, record type and UUID separated by colons. Not an organisation-wide person identity."
          },
          "reference": {
            "type": "string",
            "format": "uuid"
          },
          "record_type": {
            "type": "string",
            "enum": [
              "item",
              "claim",
              "lost_report"
            ]
          },
          "revision": {
            "type": "integer",
            "minimum": 1,
            "description": "Authoritative monotonic source revision; never second-resolution updated_at."
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string"
          },
          "venue_code": {
            "type": "string"
          },
          "staff_url": {
            "type": "string",
            "format": "uri",
            "description": "Requires ordinary staff authentication and venue membership; never a signed guest credential."
          },
          "contact": {
            "type": "object",
            "additionalProperties": false,
            "description": "Only after explicit selected lost-report event contact opt-in and current source/transport fencing. Omitted by default.",
            "properties": {
              "name": {
                "type": "string"
              },
              "email": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "phone": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        }
      }
    },
    "parameters": {
      "ActingUser": {
        "name": "X-Acting-User",
        "in": "header",
        "required": false,
        "description": "Optional. The sign-in email or user id of the active team member this request is made for. The request then runs as them: history and audit name them (and the audit trail records the key), and it may use only the scopes both the key and their role at the venue allow. Refused with 403 acting_user_refused when the person is not an active member of the venue, or acting_user_role when their role does not allow the scope. Venue keys only.",
        "schema": {
          "type": "string",
          "maxLength": 191
        }
      }
    }
  }
}
