{
  "openapi": "3.1.0",
  "info": {
    "title": "Butterchop reviewed external API",
    "version": "v1",
    "description": "Curated external actions only. Use your assigned tenant HTTPS origin. This schema is not a grant, rollout approval or provider certification."
  },
  "paths": {
    "/v1/orgs/{orgId}/network/circuits": {
      "get": {
        "operationId": "network.circuits_list",
        "summary": "List WAN circuits with current state and the applied last event",
        "description": "000101 (docs/gaps/network-wan-failover-circuits.md). Ordered by location_id, role, circuit_key. A location-bound actor sees only its own location (403 otherwise); the path org must be the actor org.",
        "tags": ["network"],
        "parameters": [
          {
            "$ref": "#/components/parameters/NetworkOrgId"
          },
          {
            "name": "location_id",
            "in": "query",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{items: NetworkCircuit[]}",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["items"],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/NetworkCircuit"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "validation_error (params.field)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkError"
                }
              }
            }
          },
          "403": {
            "description": "forbidden (capability, org or location scope)"
          }
        },
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-service-target": "isolation-unit-api",
        "x-required-capability": "network.read",
        "x-external-action": "network.circuits_list",
        "x-api-scope": "network.read",
        "x-location-authority": {
          "kind": "query",
          "param": "location_id"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": false,
        "x-grant-profile": "standard"
      }
    },
    "/v1/orgs/{orgId}/network/circuits/{circuitId}/events": {
      "get": {
        "operationId": "network.circuit_events_list",
        "summary": "Circuit timeline, newest observed first (max 500)",
        "description": "000101. observed_at >= from and < to (ISO timestamps).",
        "tags": ["network"],
        "parameters": [
          {
            "$ref": "#/components/parameters/NetworkOrgId"
          },
          {
            "$ref": "#/components/parameters/NetworkCircuitId"
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{items: NetworkCircuitEvent[]}",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["items"],
                  "properties": {
                    "items": {
                      "type": "array",
                      "maxItems": 500,
                      "items": {
                        "$ref": "#/components/schemas/NetworkCircuitEvent"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "validation_error (params.field)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkError"
                }
              }
            }
          },
          "403": {
            "description": "forbidden (capability, org or location scope)"
          },
          "404": {
            "description": "not_found"
          }
        },
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-service-target": "isolation-unit-api",
        "x-required-capability": "network.read",
        "x-external-action": "network.circuit_events_list",
        "x-api-scope": "network.read",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": false,
        "x-grant-profile": "standard"
      },
      "post": {
        "operationId": "network.circuit_events_record",
        "summary": "Record a staff / import circuit event (201; 200 on replay)",
        "description": "000101. Idempotency-Key = attempt id (header or body attempt_id). The event is appended with an apply_outcome from the circuit state rule (applied, late, conflict_tie, conflict_future, stale_sequence, note); only applied events change state. Audit network.circuit_event.recorded; applied changes emit network.circuit_state_changed and, for failover_activated, network.failover_activated.",
        "tags": ["network"],
        "parameters": [
          {
            "$ref": "#/components/parameters/NetworkOrgId"
          },
          {
            "$ref": "#/components/parameters/NetworkCircuitId"
          },
          {
            "$ref": "#/components/parameters/NetworkIdempotencyKey"
          },
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NetworkEventRecord"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replayed {event, circuit, outcome, replayed true}",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkEventRecordResult"
                }
              }
            }
          },
          "201": {
            "description": "Recorded {event, circuit, outcome, replayed false}",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkEventRecordResult"
                }
              }
            }
          },
          "400": {
            "description": "validation_error (params.field; unknown detail keys, peer = self)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkError"
                }
              }
            }
          },
          "403": {
            "description": "forbidden (capability, org or location scope)"
          },
          "404": {
            "description": "not_found circuit or peer circuit (params.field)"
          },
          "409": {
            "description": "idempotency_conflict, circuit_retired",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkError"
                }
              }
            }
          },
          "422": {
            "description": "observed_at_in_future (> DB now + 5 min), observed_at_too_old (> 400 days)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkError"
                }
              }
            }
          }
        },
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-service-target": "isolation-unit-api",
        "x-required-capability": "network.telemetry.ingest",
        "x-external-action": "network.circuit_events_ingest",
        "x-api-scope": "network.telemetry.ingest",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": false,
        "x-grant-profile": "standard"
      }
    },
    "/v1/orgs/{orgId}/network/outages": {
      "get": {
        "operationId": "network.outage_summary",
        "summary": "Derived down/degraded windows per circuit with failover and POS offline overlap",
        "description": "000101. to defaults to (and is clipped to) the DB clock, from to to − 7 days; range ≤ 92 days (else 400). Windows use applied and late link events only, never overlap per circuit and are clipped to the range; unknown start/end is reported, never assumed. pos_offline is a time-overlap correlation with offline-created orders, not causation.",
        "tags": ["network"],
        "parameters": [
          {
            "$ref": "#/components/parameters/NetworkOrgId"
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "NetworkOutageSummary",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkOutageSummary"
                }
              }
            }
          },
          "400": {
            "description": "validation_error (params.field; range above 92 days)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NetworkError"
                }
              }
            }
          },
          "403": {
            "description": "forbidden (capability, org or location scope)"
          }
        },
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-service-target": "isolation-unit-api",
        "x-required-capability": "network.read",
        "x-external-action": "network.outages_get",
        "x-api-scope": "network.read",
        "x-location-authority": {
          "kind": "query",
          "param": "location_id"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": false,
        "x-grant-profile": "standard"
      }
    },
    "/v1/orgs/{orgId}/privacy/wifi-connectors/{id}/imports": {
      "post": {
        "operationId": "wifi_portal.import",
        "tags": ["governance"],
        "summary": "Idempotency-Key required, enabled generic connector only; per-row rejection/quarantine, no inferred historical grant; stable csv:SHA256(import-key):row, changed body conflict.",
        "description": "Human bearer privacy operator required, not API-client credentials; authenticated tenant/site scope and capability enforced. Idempotency-Key required, enabled generic connector only; per-row rejection/quarantine, no inferred historical grant; stable csv:SHA256(import-key):row, changed body conflict.",
        "x-required-capability": "privacy.consent.ingest",
        "x-service-target": "isolation-unit-api",
        "security": [
          {
            "externalBearer": []
          }
        ],
        "parameters": [
          {
            "name": "orgId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Current safe projection / stable replay; delivery outcome never inferred from transport success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WifiCsvResults"
                }
              }
            }
          },
          "400": {
            "description": "Malformed body/UUID/header/CSV or invalid mapping/outbound URL pair.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WifiPortalError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid human bearer.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WifiPortalError"
                }
              }
            }
          },
          "403": {
            "description": "Missing capability, wrong tenant/site, or API-client actor.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WifiPortalError"
                }
              }
            }
          },
          "404": {
            "description": "Connector/evidence absent or hidden by tenant/site scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WifiPortalError"
                }
              }
            }
          },
          "409": {
            "description": "Changed idempotent payload, stale connector revision, already-sending delivery, missing withdrawal or unavailable accepted evidence; refresh or manual reconcile, never blind retry.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WifiPortalError"
                }
              }
            }
          },
          "422": {
            "description": "Named provider uncertified; never enable vendor adapter or infer consent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WifiPortalError"
                }
              }
            }
          },
          "503": {
            "description": "Tenant contact HMAC key unavailable; fail closed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WifiPortalError"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WifiCsvImport"
              }
            }
          }
        },
        "x-external-action": "privacy.wifi_consent_import",
        "x-api-scope": "privacy.consent.ingest",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": true,
        "x-grant-profile": "standard"
      }
    },
    "/v1/learning/xapi/statements": {
      "post": {
        "operationId": "labor.learning_xapi_statements_post",
        "summary": "Ingest strict terminal xAPI connector statements",
        "description": "API-client key or OAuth only; learning.statements.write is PII scope requiring active pii.approve approval. Live token/client scope/location intersection and exact latest effective connector approval are enforced. Namespace is xapi:<public pcc_ client_id>. Machine-created assignments/attempts carry api_client_id and null human assigned_by/recorded_by; no granting-manager or learner impersonation. Exact source replay and fingerprint conflict leave immutable receipts without another target. Retention comes only from the explicit approved connector revision. This is not a full LRS/query API. Hosted SCORM/runtime, cmi5 sessions/conformance, full LRS and live ServSafe/provider adapters remain deferred.",
        "tags": ["labor"],
        "x-service-target": "isolation-unit-api",
        "security": [
          {
            "externalBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Items with status 201 new, 200 exact replay or 409 fingerprint conflict; conflict target IDs are null and no evidence is reapplied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LearningExternalIntakeResponse"
                }
              }
            },
            "headers": {
              "RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "400": {
            "description": "Malformed JSON or missing/invalid X-Location-Id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LearningExternalError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid authentication.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LearningExternalError"
                }
              }
            }
          },
          "403": {
            "description": "Staff bearer denied; missing live PII approval, scope/location intersection or exact live connector approval (connector_mapping_not_approved).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LearningExternalError"
                }
              }
            }
          },
          "409": {
            "description": "external_assignment_conflict; source fingerprint conflicts normally appear as item status 409 in HTTP 200.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LearningExternalError"
                }
              }
            }
          },
          "422": {
            "description": "learning_external.invalid_statement, learning_external.unsupported_xapi_version, learning_external.invalid_statement_count, learner_not_active or assignment_content_mismatch.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LearningExternalError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/RateLimitUnavailable"
          }
        },
        "parameters": [
          {
            "name": "X-Experience-API-Version",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "const": "1.0.3"
            }
          },
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LearningExternalXapiRequest"
              }
            }
          }
        },
        "x-api-scope": "learning.statements.write",
        "x-external-action": "labor.learning_xapi_statements_post",
        "x-required-capability": "learning.statements.write",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": true,
        "x-grant-profile": "standard"
      }
    },
    "/v1/orgs/{orgId}/loss-prevention/journal": {
      "parameters": [
        {
          "name": "orgId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "operationId": "lp.journal_list",
        "summary": "Pull incremental sanitized transaction journal",
        "description": "Developer scope lp.journal.read requires explicit pii.approve approval because staff identifiers are included; live client/scope/location grants and audited PII reads. Immutable commit-serialized membership catches delayed source commits; disabled sources are not published. No PAN, processor_meta, approval_code, last4 or processor_payment_id. Staff session capability alone does not imply developer consent.",
        "tags": ["orgs"],
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-required-capability": "lp.journal.read",
        "x-required-scope": "lp.journal.read",
        "x-pii-scope": true,
        "x-api-scope": "lp.journal.read",
        "x-api-location": "Required location_id query parameter",
        "parameters": [
          {
            "name": "after_cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^(0|[1-9][0-9]{0,18})$"
            },
            "description": "Exclusive decimal sequence cursor bounded by signed bigint; defaults0"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "location_id",
            "in": "query",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "NDJSON one immutable journal entry per line; empty response retains cursor",
            "headers": {
              "X-Next-Cursor": {
                "description": "Decimal sequence of last returned entry or input cursor",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "description": "no-store",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/x-ndjson": {
                "schema": {
                  "type": "string",
                  "description": "Newline-delimited LpJournalEntry JSON objects"
                },
                "x-item-schema": {
                  "$ref": "#/components/schemas/LpJournalEntry"
                }
              }
            }
          },
          "403": {
            "description": "Client scope",
            "PII approval": null,
            "capability or location refusal": null
          },
          "422": {
            "description": "Invalid location",
            "cursor or limit": null
          }
        },
        "x-service-target": "isolation-unit-api",
        "x-external-action": "lp.journal_list",
        "x-location-authority": {
          "kind": "query",
          "param": "location_id"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": true,
        "x-grant-profile": "standard"
      }
    },
    "/v1/orders": {
      "get": {
        "operationId": "orders.list",
        "summary": "List orders (open checks by default; closed checks by business day)",
        "description": "status open (default; open, sent, partially_paid, newest opened first) | closed | all, optional table_number, channel and order_type. All applicable filters are ANDed before the latest 200 bound for every status. status=closed lists closed, voided and walkout orders of one business_day (default the location's current business day using its timezone and cutoff), optionally filtered by training, sorted closed_at DESC, id DESC. training is accepted with every status but filters only status=closed (ignored for open/all). Invalid channel or order_type, business_day with status open/all, an impossible date, or (status=closed) a training value other than true/false is 400 invalid_field (params.field). Since migration 000198 every order projection includes nullable cancellation_requested_by (guest or staff). Historical and separately tracked marketplace cancellations remain null, never inferred as staff. Fixed and handheld closed-check rows/detail show the recorded requester only; reopening clears this current attribution, not immutable action after_state/audit evidence.",
        "tags": ["orders"],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["open", "closed", "all"],
              "default": "open"
            }
          },
          {
            "name": "table_number",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "description": "Exact channel filter for every status; ANDed with other applicable filters before the latest 200 bound",
            "schema": {
              "type": "string",
              "enum": ["pos_fixed", "handheld", "kiosk", "qr", "web", "delivery_3p", "partner"]
            }
          },
          {
            "name": "order_type",
            "in": "query",
            "required": false,
            "description": "Exact order-type filter for every status; ANDed with other applicable filters before the latest 200 bound",
            "schema": {
              "type": "string",
              "enum": ["counter", "table", "takeout", "bar_tab", "drive_thru"]
            }
          },
          {
            "name": "business_day",
            "in": "query",
            "required": false,
            "description": "status=closed only; default the location's current business day using its timezone and cutoff",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "training",
            "in": "query",
            "required": false,
            "description": "Accepted with every status; filters status=closed only (ignored for open/all); omitted lists both",
            "schema": {
              "type": "string",
              "enum": ["true", "false"]
            }
          },
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Orders (projection as orders.get)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["items"],
                  "properties": {
                    "items": {
                      "type": "array",
                      "maxItems": 200,
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "properties": {
                          "closed_at": {
                            "type": ["string", "null"],
                            "format": "date-time"
                          },
                          "display_number": {
                            "type": ["integer", "null"]
                          },
                          "cancellation_requested_by": {
                            "type": ["string", "null"],
                            "enum": ["guest", "staff", null],
                            "description": "Current staff-attested manual cancellation source (000198); null for historical/marketplace data and after reopen, never an acting-staff identity"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "invalid_field (params.field channel, order_type, business_day, or training on status=closed)"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/RateLimitUnavailable"
          },
          "default": {
            "description": "Response defined by implementation"
          }
        },
        "x-service-target": "isolation-unit-api",
        "x-api-scope": "orders.read",
        "x-api-location": "X-Location-Id header (required for API clients)",
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-external-action": "orders.list",
        "x-required-capability": "order.ring",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": true,
        "x-grant-profile": "standard"
      }
    },
    "/v1/partner/orders": {
      "post": {
        "operationId": "partner.orders_create",
        "summary": "Delegated partner order create (gap-718): API scope orders.write, delegated grant only; external_reference idempotent (exact replay 200, changed request 409)",
        "tags": ["partner"],
        "x-service-target": "isolation-unit-api",
        "description": "Delegated partner order create (gap-718): API scope orders.write, delegated grant only (machine tokens rejected); X-Location-Id must be in the grant and is the only location source (unknown body keys, including location_id, rejected). Body {external_reference, order_type, items[{menu_item_id, qty, variant_id?, modifiers?[{modifier_id, qty?}]}] (1..100), guest_name?, guest_phone?, guest_count?, revenue_center_id?, pickup?: {scheduled_for?}}. Pickup (gap-337) requires order_type takeout: scheduled_for books promised_at under the location's scheduled-order lead/cutoff/blackout/capacity policy (422/409); without it the order carries the current pickup quote as quoted_ready_at (an estimate, not a promise). A paused marketplace refuses 409 ordering_paused; training refuses 409 training_unsupported; no payment claim is accepted (the guest pays through POST /v1/partner/orders/{id}/payment). Every create audits partner.order_created. external_reference is idempotent per API client: an exact replay returns 200 with the same order; a changed request or a reused reference returns 409; a failing item or gate rolls back the receipt, order and lines. Returns 201 {id,location_id,status,revision,promised_at,quoted_ready_at,read_url} with no prices, totals, payments, approval or training state accepted from the client. The stored order channel is partner. A reference that was cancelled before the create returns 409 order_cancelled and creates nothing.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PartnerOrderCreateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Exact replay of an existing external_reference; returns the existing order",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerOrder"
                }
              }
            }
          },
          "201": {
            "description": "Order created. The order channel is partner.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerOrder"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Authentication required"
          },
          "403": {
            "description": "Missing capability or scope, delegated grant required, or location outside the grant"
          },
          "409": {
            "description": "external_reference already used for a different request, order_cancelled (the partner cancelled the reference first), ordering_paused, training_unsupported, or scheduled pickup capacity full"
          },
          "422": {
            "description": "Scheduled pickup time invalid, too soon, past cutoff or on a blackout date"
          }
        },
        "x-required-capability": "order.ring",
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-external-action": "partner.orders_create",
        "x-api-scope": "orders.write",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["oauth_delegated"],
        "x-pii": true,
        "x-grant-profile": "standard",
        "parameters": [
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      },
      "get": {
        "operationId": "partner.orders_lookup",
        "summary": "Client-scoped order lookup by external_reference for ambiguous create retries (gap-337): scope orders.read",
        "tags": ["partner"],
        "x-service-target": "isolation-unit-api",
        "description": "Client-scoped lookup of an order created through POST /v1/partner/orders (gap-337), for a create whose response was lost or timed out. API scope orders.read (staff order.ring), X-Location-Id from the grant. Query external_reference (required, 1..200 characters). Matches only a receipt of the calling API client at that location; a reference used by another client, an unknown reference and a training order all return 404. Returns {external_reference, order:{id,location_id,status,revision,promised_at,quoted_ready_at,read_url}}; no guest data, prices or totals. Safe to repeat: it creates and changes nothing.",
        "responses": {
          "200": {
            "description": "Order created earlier by this client with this external_reference",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerOrderLookup"
                }
              }
            }
          },
          "400": {
            "description": "external_reference missing or invalid"
          },
          "401": {
            "description": "Authentication required"
          },
          "403": {
            "description": "Missing capability or scope, or location outside the grant"
          },
          "404": {
            "description": "No order for this client, location and external_reference"
          }
        },
        "x-required-capability": "order.ring",
        "security": [
          {
            "externalBearer": []
          }
        ],
        "parameters": [
          {
            "name": "external_reference",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-external-action": "partner.orders_lookup",
        "x-api-scope": "orders.read",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": true,
        "x-grant-profile": "standard"
      }
    },
    "/v1/partner/orders/cancellations": {
      "post": {
        "operationId": "partner.orders_cancel",
        "summary": "Cancel an order by external reference, also before the create arrives (gap-337): scope orders.write, delegated grant only",
        "tags": ["partner"],
        "x-service-target": "isolation-unit-api",
        "security": [
          {
            "externalBearer": []
          }
        ],
        "description": "Cancel by external_reference for the calling API client. API scope orders.write, delegated grant only; X-Location-Id must be in the grant. Body {external_reference, reason?: guest_cancelled|partner_cancelled|duplicate|other}. No order for the reference yet: a tombstone is stored, 201 state cancelled_before_create with order null, and a later POST /v1/partner/orders with this reference returns 409 order_cancelled and creates nothing. Order exists and no tender touched it: the order is voided like a marketplace cancel (station VOID notice for fired lines), 201 state voided. An order with an approved or in-progress payment returns 409 order_has_payment; refunds stay with the tender owner. A closed or voided order returns 409 order_not_cancellable. A repeat returns 200 with replayed true and the same state. Audits partner.order_cancelled or partner.order_cancelled_before_create; no guest data in the audit.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PartnerOrderCancelRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Repeat of an earlier cancel of this reference",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerOrderCancel"
                }
              }
            }
          },
          "201": {
            "description": "Cancel recorded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerOrderCancel"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "401": {
            "description": "Authentication required"
          },
          "403": {
            "description": "Missing capability or scope, delegated grant required, or location outside the grant"
          },
          "404": {
            "description": "The reference belongs to an order at another location"
          },
          "409": {
            "description": "order_has_payment or order_not_cancellable"
          }
        },
        "x-required-capability": "order.ring",
        "x-external-action": "partner.orders_cancel",
        "x-api-scope": "orders.write",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["oauth_delegated"],
        "x-pii": true,
        "x-grant-profile": "standard",
        "parameters": [
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ]
      }
    },
    "/v1/partner/delivery/quote": {
      "post": {
        "operationId": "partner.delivery_fee_estimate",
        "summary": "Read-only non-binding partner delivery fee estimate (gap-720)",
        "tags": ["partner"],
        "x-service-target": "isolation-unit-api",
        "x-required-capability": "order.ring",
        "security": [
          {
            "externalBearer": []
          }
        ],
        "description": "Requires delivery.quote scope, live approved client/connection and X-Location-Id matching body location_id. Shared per-client minute/day rate limits; fail closed503 if limiter unavailable. Estimates only: no quote token, order, payment, dispatch or notification. Postcode membership is configured zone feasibility, not courier or street-address deliverability. Missing/unsupported geography yields eligible=false/serviceability_unknown. Recompute canonical server-priced destination quote at admission; revision/expiry never lock fees or delivery time. No postcode echo or storage. SELECT-only domain transaction with canonical location configuration lock; normal redacted API audit/rate accounting remains. Empty fee rules explicitly zero_fee in active location currency; no USD fallback. All minor strings use repository scale4 (10000 per major unit).",
        "parameters": [
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": ["location_id", "zone_id", "subtotal_minor", "currency"],
                "properties": {
                  "location_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "zone_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "subtotal_minor": {
                    "type": "string",
                    "pattern": "^(?:0|[1-9][0-9]{0,18})$"
                  },
                  "currency": {
                    "type": "string",
                    "pattern": "^[A-Z]{3}$"
                  },
                  "delivery_address_or_postcode": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": ["country_code", "postcode"],
                    "properties": {
                      "country_code": {
                        "type": "string",
                        "minLength": 2,
                        "maxLength": 2
                      },
                      "postcode": {
                        "type": "string",
                        "maxLength": 32
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Non-binding estimate with fees[{id,kind,fee_minor,waived}], fee_configuration rules|zero_fee, total_fee_minor, location_id, zone_id, currency, eligible, reason_codes, feasibility, as_of, expires_at, SHA256 policy_revision, estimate{basis configured|unknown,estimated_delivery_from nullable,estimated_delivery_to nullable}, binding non_binding_estimate. No quote_id/proof; Cache-Control no-store.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PartnerDeliveryFeeEstimate"
                }
              }
            }
          },
          "400": {
            "description": "Strict DTO, invalid/oversized subtotal, header/body mismatch or inactive zone"
          },
          "401": {
            "description": "Authentication required"
          },
          "403": {
            "description": "Missing exact scope, capability, location or active integration authority"
          },
          "404": {
            "description": "Foreign/unmapped zone or inactive/missing location"
          },
          "409": {
            "description": "training_unsupported"
          },
          "422": {
            "description": "currency_mismatch, delivery_policy_missing or unsupported postcode country"
          },
          "429": {
            "description": "Shared per-client rate limit exceeded"
          },
          "503": {
            "description": "Rate limiter unavailable (fail closed)"
          }
        },
        "x-external-action": "partner.delivery_fee_estimate",
        "x-api-scope": "delivery.quote",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": false,
        "x-grant-profile": "standard"
      }
    },
    "/v1/menu/nutrition-versions/{id}": {
      "get": {
        "operationId": "menu.nutrition_versions_get",
        "summary": "Fetch authoritative current public nutrition version or tombstone",
        "tags": ["catalog"],
        "x-service-target": "isolation-unit-api",
        "x-required-capability": "menu.manage",
        "security": [
          {
            "externalBearer": []
          }
        ],
        "description": "Migration000145 authored contract; registered developer action menu.nutrition_versions_get requires menu.read and delegates menu.manage. Human menu managers may also read. Developer action is registered; schema, public source hooks and worker activation require explicit145 rollout grant. Per-request effective credential and live database grants are both enforced: active/unexpired/unrevoked identity.api_clients, current menu.read scope/location grant and active integration connection. Revoked or reduced client grants deny403 immediately; cached credential data cannot authorize stale grants. X-Location-Id is required; unknown source_kind400; tenant/foreign/wrong-location subject404. All JSON private,no-store. Returns current source_version as integer version and per-owner monotonic decimal-string revision, whitelist-only projection when approved, or tombstone=true/projection=null for invalidated/withdrawn/expired authority. Source owner lifecycle/effective/expiry rechecked. Never returns previous approved value. Consumers dedupe stable event ID, compare revision and fetch this authoritative URL before applying. Receipt2xx is received only; publication applied requires separate food-owner evidence. Exact tenant/location owner context pins the reviewed menu labeling release and profile version, or exact guest publication UUID; namespace/type/reviewer flags alone are insufficient. Internal release/profile/publication IDs never appear in the minimal public envelope. No legacy source-kind alias is accepted.",
        "responses": {
          "200": {
            "description": "Authoritative response",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "private, no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NutritionWebhookVersion"
                }
              }
            }
          },
          "400": {
            "description": "Malformed subject/location UUID, missing X-Location-Id, unknown source_kind; bad_request or nutrition_webhook.source_invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NutritionWebhookError"
                }
              }
            }
          },
          "401": {
            "description": "Authentication required.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NutritionWebhookError"
                }
              }
            }
          },
          "403": {
            "description": "Missing menu.manage or effective/live menu.read client scope/location grant, revoked/reduced/expired credential or inactive integration connection; forbidden / nutrition_webhook.client_scope_denied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NutritionWebhookError"
                }
              }
            }
          },
          "404": {
            "description": "Subject not found for actor tenant, selected source_kind and X-Location-Id; foreign/wrong-location404.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NutritionWebhookError"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Food assertion canonical subject UUID, or location UUID for guest source."
          },
          {
            "name": "source_kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["menu_labeling_release", "guest_nutrition_projection"],
              "default": "menu_labeling_release"
            },
            "description": "Owner discriminator; guest canonical subject is the location UUID."
          },
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "x-required-api-scope": "menu.read",
        "x-external-action": "menu.nutrition_versions_get",
        "x-api-scope": "menu.read",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": false,
        "x-grant-profile": "standard"
      }
    },
    "/v1/orgs/{orgId}/export-subscriptions/{subscriptionId}/deliveries": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WarehouseOrgId"
        },
        {
          "name": "subscriptionId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        }
      ],
      "get": {
        "operationId": "exports.deliveries_list",
        "summary": "Pull committed delivery manifests",
        "description": "Human analytics.export.manage or explicitly resource-registered API-client exports.read. Active full-field warehouse_export grant; exact purpose/recipient/dataset/bucket/prefix, approved relationship_scope.api_client_ids, matching active integration and live intersected client locations must cover EVERY subscription site; partial intersection refuses. Live credential/client status and scope rechecked. Cross-org404. No API administration. Committed only, ordered sequence, maximum100.",
        "tags": ["orgs"],
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-required-capability": "analytics.export.manage",
        "x-service-target": "isolation-unit-api",
        "responses": {
          "200": {
            "description": "Items",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": ["items"],
                  "properties": {
                    "items": {
                      "type": "array",
                      "maxItems": 100,
                      "items": {
                        "$ref": "#/components/schemas/WarehouseDelivery"
                      }
                    }
                  }
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/WarehouseError"
          }
        },
        "parameters": [
          {
            "name": "after_sequence",
            "in": "query",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,18}$",
              "default": "0"
            }
          }
        ],
        "x-api-scope": "exports.read",
        "x-api-location": "Full subscription location_scope must fit live intersected client/token locations; explicit grant-approved client UUID and matching active integration",
        "x-external-action": "exports.deliveries_list",
        "x-location-authority": {
          "kind": "warehouse_export_resource"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": false,
        "x-grant-profile": "standard"
      }
    },
    "/v1/orgs/{orgId}/export-deliveries/{deliveryId}/files/{fileIndex}/url": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WarehouseOrgId"
        },
        {
          "name": "deliveryId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid"
          }
        },
        {
          "name": "fileIndex",
          "in": "path",
          "required": true,
          "schema": {
            "type": "integer",
            "minimum": 0
          }
        }
      ],
      "post": {
        "operationId": "exports.delivery_file_url",
        "summary": "Issue read-only hosted file GET URL",
        "description": "Human analytics.export.manage or explicitly resource-registered API-client exports.read. Active full-field warehouse_export grant; exact purpose/recipient/dataset/bucket/prefix, approved relationship_scope.api_client_ids, matching active integration and live intersected client locations must cover EVERY subscription site; partial intersection refuses. Live credential/client status and scope rechecked. Cross-org404. No API administration. No body. Resource-bound read-only POST, never general POST write authorization. Grant/fullscope checked immediately before issuance.422 customer bucket,404 unknown/uncommitted/index. Revocation cannot retract already-issued URL; expires900 seconds.",
        "tags": ["orgs"],
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-required-capability": "analytics.export.manage",
        "x-service-target": "isolation-unit-api",
        "responses": {
          "200": {
            "description": "Result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WarehouseFileUrl"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/WarehouseError"
          }
        },
        "x-api-scope": "exports.read",
        "x-api-location": "Full delivery subscription location_scope must fit live intersected client/token locations; explicit grant-approved client UUID and matching active integration",
        "x-external-action": "exports.delivery_file_url",
        "x-location-authority": {
          "kind": "warehouse_export_resource"
        },
        "x-principal-kinds": ["oauth_delegated", "confidential_machine", "api_key"],
        "x-pii": false,
        "x-grant-profile": "standard"
      }
    },
    "/v1/foodsafety/exports/{exportId}": {
      "get": {
        "operationId": "foodsafety.export_get",
        "summary": "Read one food-safety export snapshot",
        "description": "Staff with food_safety.manage and a location grant, or an inspector API client: X-Location-Id must equal the snapshot location, and the snapshot location, from/to dates and report type food_safety_pdf_export must lie inside the grant on every request (403 grant_out_of_bounds, also after the grant is narrowed). Inspector clients only see inspector-profile snapshots (404 otherwise). Revoked or expired grants get 401 invalid_token.",
        "tags": ["foodsafety"],
        "parameters": [
          {
            "$ref": "#/components/parameters/FoodSafetyExportId"
          },
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FoodSafetyExportView"
                }
              }
            }
          },
          "401": {
            "description": "invalid_token (revoked or expired API credential)"
          },
          "403": {
            "description": "Missing capability or location grant, or grant_out_of_bounds",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FoodSafetyExportError"
                }
              }
            }
          },
          "404": {
            "description": "Missing id, another tenant, or an internal-profile snapshot for an inspector",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FoodSafetyExportError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/RateLimitUnavailable"
          }
        },
        "x-service-target": "isolation-unit-api",
        "x-required-capability": "food_safety.manage",
        "x-api-scope": "food_safety.inspection.read",
        "x-api-location": "X-Location-Id header (required for API clients; must equal the snapshot location); inspector grants bound the snapshot's from/to dates and need report type food_safety_pdf_export",
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-external-action": "food_safety.pdf_export.get",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["confidential_machine", "api_key"],
        "x-pii": false,
        "x-grant-profile": "inspector"
      }
    },
    "/v1/foodsafety/exports/{exportId}/download": {
      "get": {
        "operationId": "foodsafety.export_download",
        "summary": "Download the rendered food-safety export PDF",
        "description": "Same authorization as foodsafety.export_get, re-checked on every call; every access is audited as foodsafety.export.downloaded. Bytes are verified against the registered document sha256. No URL or token is issued or logged.",
        "tags": ["foodsafety"],
        "parameters": [
          {
            "$ref": "#/components/parameters/FoodSafetyExportId"
          },
          {
            "name": "X-Location-Id",
            "in": "header",
            "required": true,
            "description": "Required by external API location authorization, including all-location grants.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The PDF",
            "headers": {
              "Content-Disposition": {
                "description": "attachment; filename=\"food-safety-<export_id>.pdf\"",
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              },
              "X-Content-Type-Options": {
                "schema": {
                  "type": "string",
                  "const": "nosniff"
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "invalid_token (revoked or expired API credential)"
          },
          "403": {
            "description": "Missing capability or location grant, or grant_out_of_bounds",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FoodSafetyExportError"
                }
              }
            }
          },
          "404": {
            "description": "Missing id, another tenant, or an internal-profile snapshot for an inspector",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FoodSafetyExportError"
                }
              }
            }
          },
          "409": {
            "description": "export_not_ready (current.state)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FoodSafetyExportError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "storage_unavailable (store unreachable or stored bytes do not match the sha256), or rate_limit_unavailable for API clients",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FoodSafetyExportError"
                }
              }
            }
          }
        },
        "x-service-target": "isolation-unit-api",
        "x-required-capability": "food_safety.manage",
        "x-api-scope": "food_safety.inspection.read",
        "x-api-location": "X-Location-Id header (required for API clients; must equal the snapshot location); inspector grants bound the snapshot's from/to dates and need report type food_safety_pdf_export",
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-external-action": "food_safety.pdf_export.download",
        "x-location-authority": {
          "kind": "header"
        },
        "x-principal-kinds": ["confidential_machine", "api_key"],
        "x-pii": false,
        "x-grant-profile": "inspector"
      }
    },
    "/v1/orgs/{orgId}/mcp": {
      "post": {
        "operationId": "mcp.endpoint",
        "summary": "Remote MCP server (JSON-RPC 2.0 over Streamable HTTP, read-only tools)",
        "description": "docs/gaps/analytics-ai-mcp-analytics-qa.md. Stateless; JSON responses only; protocol versions 2025-11-25, 2025-06-18, 2025-03-26 (optional MCP-Protocol-Version header). One JSON-RPC object per request (batches refused). Methods initialize, ping, tools/list, tools/call. Tools: list_locations, get_sales_summary, compare_sales_periods, get_labor_summary, get_item_mix, get_inventory_alerts, get_review_summary, list_equipment, get_equipment, list_reports, get_tax_report, get_profit_and_loss and list_coupons. Equipment tools also require facilities.read and live facilities.asset_register; service schedules require live facilities.preventive_maintenance. Equipment output excludes serial numbers, other identifiers, vendors, contacts, costs and notes; it never certifies safety or changes assets. Delivery tools (explicit opt-in: the client must hold delivery.read in addition to analytics.mcp): delivery_quote needs live order.ring, delivery_history, delivery_status and delivery_report need live delivery.tracking.read and dispatch.read. A quote needs only country and postcode plus at most 20 menu lines, saves nothing and creates no order; history pages hold at most 50 rows. Output has opaque ids, states, times, counts and decimal-string fees only: no customer, address, driver, GPS, reason or order data, and states are recorded evidence, not proof of receipt. Proposal tools (scope automation.propose; names with _propose_: delivery assign, complete, correct, cancel and marketplace order decision; order create; table assignment; reservation create and change; menu availability; own clock in and out; own leave request) only record a pending proposal that expires after 30 minutes (10 minutes for a clock proposal). A different person must approve it in the app (governance.mcp_proposal_approve) and the live right of the granting staff member is checked again then. Read tools dispatch_open_tasks, dispatch_drivers (dispatch.read), marketplace_open_orders (delivery.order_decide; both with delivery.read) and floor_targets (automation.propose, order.ring) list the ids a proposal needs. list_reports (reports.read) lists the report catalog entries the staff member's live capabilities allow, in pages of at most 50; get_tax_report (tax.read, finance.tax.manage) returns the tax-by-rate catalog report, not a filed return; get_profit_and_loss (finance.statements.read scope and capability) is refused unless every location of the owning entity is granted; list_coupons (promotions.read, promotion.manage) returns no redemptions or guest details; get_staff_performance (staff.performance.read, report.z and labor.manage, and a recorded PII approval on the client) returns net sales and refunds by check owner with staff names and ids, and no tips, hours or pay. tools/list shows only those the token's data scopes and the approving staff member's live capabilities allow. The endpoint admits a staff member who holds report.z or any capability that backs a tool, so a custom role without report.z reaches only the tools its own capability allows; otherwise 403 capability_not_granted. Each tools/call re-checks scope (403 insufficient_scope), arguments (-32602; at most 92 days) and the location grant (403 location_not_granted), reserves monthly quota (exhausted = tool error with reset time) and is audited (mcp.tool.called) without argument values. 503 unless MCP_ENABLED and not MCP_KILL_SWITCH.",
        "tags": ["mcp"],
        "parameters": [
          {
            "$ref": "#/components/parameters/ApiClientOrgId"
          },
          {
            "name": "MCP-Protocol-Version",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "enum": ["2025-11-25", "2025-06-18", "2025-03-26"]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/McpJsonRpcMessage"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "JSON-RPC response (result, or error for -32601/-32602; tool failures are results with isError true)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpJsonRpcResponse"
                }
              }
            }
          },
          "202": {
            "description": "Notification or client response accepted (no body)"
          },
          "400": {
            "description": "Parse error (-32700), invalid request or batch (-32600), unsupported MCP-Protocol-Version",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/McpJsonRpcResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing, expired or revoked OAuth access token. WWW-Authenticate: Bearer error=\"invalid_token\", resource_metadata=\"<origin>/.well-known/oauth-protected-resource/v1/orgs/{orgId}\""
          },
          "403": {
            "description": "insufficient_scope (WWW-Authenticate names the step-up scope), location_not_granted, delegated_grant_required, origin_not_allowed, capability_not_granted (report.z)"
          },
          "413": {
            "description": "Body over 64 KiB"
          },
          "415": {
            "description": "Content-Type is not application/json"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "description": "mcp_unavailable (disabled or kill switch) or rate_limit_unavailable"
          }
        },
        "x-service-target": "isolation-unit-api",
        "x-api-scope": "analytics.mcp",
        "x-api-location": "Per tool call (arguments.location_id), checked against the grant on every call",
        "security": [
          {
            "externalBearer": []
          }
        ],
        "x-external-action": "mcp.endpoint",
        "x-required-capability": "report.z",
        "x-location-authority": {
          "kind": "tool"
        },
        "x-principal-kinds": ["oauth_delegated"],
        "x-pii": false,
        "x-grant-profile": "standard"
      }
    }
  },
  "components": {
    "parameters": {
      "NetworkOrgId": {
        "name": "orgId",
        "in": "path",
        "required": true,
        "description": "Must equal the actor organization (403 otherwise)",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "NetworkCircuitId": {
        "name": "circuitId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "NetworkIdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "1..200 characters; required unless the body carries idempotency_key (create) or attempt_id (circuit event). The same key and body replays (200 replayed true); a different body is 409 idempotency_conflict.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        }
      },
      "WarehouseOrgId": {
        "name": "orgId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "FoodSafetyExportId": {
        "name": "exportId",
        "in": "path",
        "required": true,
        "description": "Export snapshot id (404 when not a UUID or not visible)",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "ApiClientOrgId": {
        "name": "orgId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "schemas": {
      "NetworkCircuit": {
        "type": "object",
        "description": "000101 governance.network_circuits row plus the applied last event.",
        "required": [
          "id",
          "org_id",
          "location_id",
          "circuit_key",
          "provider_id",
          "provider_circuit_ref",
          "role",
          "access_type",
          "edge_device_endpoint_id",
          "connectivity_edge_key",
          "down_mbps",
          "up_mbps",
          "data_cap_mb",
          "cap_reset_day",
          "overage_rate",
          "overage_unit",
          "currency",
          "usage_pool_id",
          "usage_alert_thresholds",
          "state",
          "last_event_at",
          "last_event_id",
          "last_event_sequence",
          "revision",
          "created_by",
          "updated_by",
          "created_at",
          "updated_at",
          "last_event"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "location_id": {
            "type": "string",
            "format": "uuid"
          },
          "circuit_key": {
            "type": "string",
            "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,99}$"
          },
          "provider_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "provider_circuit_ref": {
            "type": ["string", "null"]
          },
          "role": {
            "$ref": "#/components/schemas/NetworkCircuitRole"
          },
          "access_type": {
            "$ref": "#/components/schemas/NetworkAccessType"
          },
          "edge_device_endpoint_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "connectivity_edge_key": {
            "type": ["string", "null"]
          },
          "down_mbps": {
            "type": ["string", "null"],
            "description": "numeric(10,2) as text, e.g. \"500.00\""
          },
          "up_mbps": {
            "type": ["string", "null"]
          },
          "data_cap_mb": {
            "type": ["string", "null"],
            "description": "bigint as text"
          },
          "cap_reset_day": {
            "type": ["integer", "null"],
            "minimum": 1,
            "maximum": 28
          },
          "overage_rate": {
            "type": ["string", "null"],
            "description": "000175 numeric(19,4) as text per overage_unit (estimate pricing)"
          },
          "overage_unit": {
            "type": ["string", "null"],
            "enum": ["mb", "gb", null]
          },
          "currency": {
            "type": ["string", "null"],
            "pattern": "^[A-Z]{3}$"
          },
          "usage_pool_id": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "000175 pooled allowance member (no own cap or rate)"
          },
          "usage_alert_thresholds": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            },
            "minItems": 1,
            "maxItems": 10
          },
          "state": {
            "$ref": "#/components/schemas/NetworkCircuitState"
          },
          "last_event_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "last_event_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "last_event_sequence": {
            "type": ["string", "null"]
          },
          "revision": {
            "type": "integer",
            "minimum": 1
          },
          "created_by": {
            "type": "string",
            "format": "uuid"
          },
          "updated_by": {
            "type": "string",
            "format": "uuid"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_event": {
            "description": "The applied event behind state",
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "required": ["id", "event_type", "observed_at", "source", "apply_outcome"],
                "properties": {
                  "id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "event_type": {
                    "$ref": "#/components/schemas/NetworkEventType"
                  },
                  "observed_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "source": {
                    "type": "string",
                    "enum": ["connector", "staff", "import"]
                  },
                  "apply_outcome": {
                    "$ref": "#/components/schemas/NetworkApplyOutcome"
                  }
                }
              }
            ]
          }
        }
      },
      "NetworkCircuitRole": {
        "type": "string",
        "enum": ["primary", "backup", "tertiary", "out_of_band"]
      },
      "NetworkAccessType": {
        "type": "string",
        "enum": ["fiber", "cable", "dsl", "fixed_wireless", "lte", "5g", "satellite", "other"]
      },
      "NetworkCircuitState": {
        "type": "string",
        "enum": ["planned", "active", "down", "degraded", "standby", "retired"]
      },
      "NetworkEventType": {
        "type": "string",
        "enum": [
          "down",
          "up",
          "degraded",
          "recovered",
          "failover_activated",
          "failback",
          "flapping",
          "manual_note",
          "lifecycle_changed"
        ]
      },
      "NetworkApplyOutcome": {
        "type": "string",
        "description": "applied = changed current state; late = older than current state (timeline only); conflict_tie = same time as the current state, no newer sequence; conflict_future = observed more than 5 min ahead of the server; stale_sequence = older provider sequence; note = manual_note.",
        "enum": ["applied", "late", "conflict_tie", "conflict_future", "stale_sequence", "note"]
      },
      "NetworkError": {
        "type": "object",
        "description": "000101 network operations error body.",
        "required": ["code", "message"],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "params": {
            "type": "object",
            "additionalProperties": true
          },
          "current": {
            "type": ["object", "null"],
            "additionalProperties": true
          }
        }
      },
      "NetworkCircuitEvent": {
        "type": "object",
        "description": "000101 governance.network_circuit_events row (append-only).",
        "required": [
          "id",
          "org_id",
          "location_id",
          "circuit_id",
          "event_type",
          "peer_circuit_id",
          "observed_at",
          "recorded_at",
          "source",
          "connector_id",
          "recorded_by",
          "external_event_id",
          "provider_sequence",
          "detail",
          "payload_hash",
          "attempt_id",
          "apply_outcome",
          "from_state",
          "to_state"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "org_id": {
            "type": "string",
            "format": "uuid"
          },
          "location_id": {
            "type": "string",
            "format": "uuid"
          },
          "circuit_id": {
            "type": "string",
            "format": "uuid"
          },
          "event_type": {
            "$ref": "#/components/schemas/NetworkEventType"
          },
          "peer_circuit_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "observed_at": {
            "type": "string",
            "format": "date-time"
          },
          "recorded_at": {
            "type": "string",
            "format": "date-time"
          },
          "source": {
            "type": "string",
            "enum": ["connector", "staff", "import"]
          },
          "connector_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "recorded_by": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "external_event_id": {
            "type": ["string", "null"]
          },
          "provider_sequence": {
            "type": ["string", "null"]
          },
          "detail": {
            "$ref": "#/components/schemas/NetworkEventDetail"
          },
          "payload_hash": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$"
          },
          "attempt_id": {
            "type": "string"
          },
          "apply_outcome": {
            "$ref": "#/components/schemas/NetworkApplyOutcome"
          },
          "from_state": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/NetworkCircuitState"
              },
              {
                "type": "null"
              }
            ]
          },
          "to_state": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/NetworkCircuitState"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "NetworkEventDetail": {
        "type": "object",
        "description": "Redacted selected fields only; staff input is strict (unknown keys → 400).",
        "additionalProperties": false,
        "properties": {
          "loss_pct": {
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "latency_ms": {
            "type": "number",
            "minimum": 0,
            "maximum": 600000
          },
          "jitter_ms": {
            "type": "number",
            "minimum": 0,
            "maximum": 600000
          },
          "reason_code": {
            "type": "string",
            "pattern": "^[A-Za-z0-9_.:-]{1,100}$"
          },
          "note": {
            "type": "string",
            "minLength": 1,
            "maxLength": 1000
          },
          "lifecycle_reason": {
            "type": "string",
            "description": "Set by the server on lifecycle_changed events"
          }
        }
      },
      "NetworkEventRecord": {
        "type": "object",
        "required": ["event_type", "observed_at"],
        "properties": {
          "attempt_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Alternative to the Idempotency-Key header"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "down",
              "up",
              "degraded",
              "recovered",
              "failover_activated",
              "failback",
              "flapping",
              "manual_note"
            ]
          },
          "observed_at": {
            "type": "string",
            "format": "date-time"
          },
          "peer_circuit_id": {
            "type": ["string", "null"],
            "format": "uuid",
            "description": "Same location",
            "not the circuit itself": null
          },
          "source": {
            "type": "string",
            "enum": ["staff", "import"],
            "default": "staff"
          },
          "detail": {
            "$ref": "#/components/schemas/NetworkEventDetail"
          }
        }
      },
      "NetworkEventRecordResult": {
        "type": "object",
        "required": ["event", "circuit", "outcome", "replayed"],
        "properties": {
          "event": {
            "$ref": "#/components/schemas/NetworkCircuitEvent"
          },
          "circuit": {
            "$ref": "#/components/schemas/NetworkCircuit"
          },
          "outcome": {
            "$ref": "#/components/schemas/NetworkApplyOutcome"
          },
          "replayed": {
            "type": "boolean"
          }
        }
      },
      "NetworkOutageSummary": {
        "type": "object",
        "description": "000101 derived outage read model.",
        "required": ["from", "to", "generated_at", "items"],
        "properties": {
          "from": {
            "type": "string",
            "format": "date-time"
          },
          "to": {
            "type": "string",
            "format": "date-time"
          },
          "generated_at": {
            "type": "string",
            "format": "date-time"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "circuit_id",
                "circuit_key",
                "location_id",
                "role",
                "access_type",
                "state",
                "state_at_from",
                "evidence",
                "windows"
              ],
              "properties": {
                "circuit_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "circuit_key": {
                  "type": "string"
                },
                "location_id": {
                  "type": "string",
                  "format": "uuid"
                },
                "role": {
                  "$ref": "#/components/schemas/NetworkCircuitRole"
                },
                "access_type": {
                  "$ref": "#/components/schemas/NetworkAccessType"
                },
                "state": {
                  "$ref": "#/components/schemas/NetworkCircuitState"
                },
                "state_at_from": {
                  "type": "string",
                  "enum": ["up", "down", "degraded", "unknown"]
                },
                "evidence": {
                  "type": "object",
                  "required": ["event_count", "conflict_count", "latest_recorded_at"],
                  "properties": {
                    "event_count": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "conflict_count": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "latest_recorded_at": {
                      "type": ["string", "null"],
                      "format": "date-time"
                    }
                  }
                },
                "windows": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/NetworkOutageWindow"
                  }
                }
              }
            }
          }
        }
      },
      "NetworkOutageWindow": {
        "type": "object",
        "required": [
          "kind",
          "start_at",
          "start_clipped",
          "start_event_id",
          "end_at",
          "end_clipped",
          "end_event_id",
          "end_known",
          "duration_seconds",
          "minimum_duration_seconds",
          "failover",
          "sources",
          "pos_offline"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": ["down", "degraded"]
          },
          "start_at": {
            "type": "string",
            "format": "date-time"
          },
          "start_clipped": {
            "type": "boolean"
          },
          "start_event_id": {
            "type": "string",
            "format": "uuid"
          },
          "end_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "end_clipped": {
            "type": "boolean"
          },
          "end_event_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "end_known": {
            "type": "boolean"
          },
          "duration_seconds": {
            "type": ["integer", "null"],
            "description": "Duration inside the range; null = no recovery observed"
          },
          "minimum_duration_seconds": {
            "type": "integer",
            "description": "Lower bound",
            "always set": null
          },
          "failover": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "required": [
                  "started_at",
                  "started_clipped",
                  "event_id",
                  "backup_circuit_id",
                  "duration_seconds"
                ],
                "properties": {
                  "started_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "started_clipped": {
                    "type": "boolean"
                  },
                  "event_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "backup_circuit_id": {
                    "type": ["string", "null"],
                    "format": "uuid"
                  },
                  "duration_seconds": {
                    "type": ["integer", "null"]
                  }
                }
              }
            ]
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["connector", "staff", "import"]
            }
          },
          "pos_offline": {
            "description": "Down windows only; time-overlap correlation, not causation",
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "required": [
                  "correlation",
                  "offline_order_count",
                  "first_offline_order_at",
                  "last_offline_order_at"
                ],
                "properties": {
                  "correlation": {
                    "type": "string",
                    "enum": ["time_overlap"]
                  },
                  "offline_order_count": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "first_offline_order_at": {
                    "type": ["string", "null"],
                    "format": "date-time"
                  },
                  "last_offline_order_at": {
                    "type": ["string", "null"],
                    "format": "date-time"
                  }
                }
              }
            ]
          }
        }
      },
      "WifiCsvResults": {
        "type": "object",
        "properties": {
          "rows": {
            "type": "array",
            "maxItems": 1000,
            "items": {
              "$ref": "#/components/schemas/WifiCsvRow"
            }
          }
        },
        "required": ["rows"],
        "additionalProperties": false
      },
      "WifiCsvRow": {
        "type": "object",
        "properties": {
          "row": {
            "type": "integer",
            "minimum": 1
          },
          "event_id": {
            "type": "string",
            "format": "uuid"
          },
          "outcome": {
            "type": "string",
            "enum": ["applied", "replay", "quarantined", "rejected", "conflict"]
          },
          "replay": {
            "type": "boolean"
          },
          "original_outcome": {
            "type": "string",
            "enum": ["applied", "replay", "quarantined", "rejected"]
          },
          "quarantine_reason": {
            "type": ["string", "null"]
          },
          "consent_event_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "customer_record_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "reason": {
            "type": ["string", "null"]
          }
        },
        "required": ["row", "outcome"],
        "additionalProperties": false,
        "description": "Invalid rows rejected as invalid_row/invalid_contact; valid row AppError<500 isolated with savepoint and redacted rejected observation. Infrastructure503 aborts batch, never fake row success. Stable csv:SHA256(import-key):row; no fabricated vendor guest identity or historical grant."
      },
      "WifiPortalError": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "params": {
            "type": "object",
            "additionalProperties": true
          },
          "current": {}
        },
        "required": ["code", "message"],
        "description": "Canonical AppError; no partner raw payload/contact/signature/secret in error evidence."
      },
      "WifiCsvImport": {
        "type": "object",
        "properties": {
          "csv": {
            "type": "string",
            "maxLength": 1048576,
            "writeOnly": true,
            "description": "UTF-8 ≤1MB, ≤1000 rows. Allowed header guest_id,email,phone,choice,captured_at,notice_ref,consent_text_sha256,explicit_choice,reconsent_proof; one contact; choice granted/withdrawn; explicit_choice literal true required for grant. Missing historic evidence quarantines; csv:<SHA256(import-key)>:<row> stable identity."
          }
        },
        "required": ["csv"],
        "additionalProperties": false
      },
      "LearningExternalIntakeResponse": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LearningExternalIntakeResult"
            },
            "minItems": 1,
            "maxItems": 100
          }
        },
        "required": ["items"],
        "additionalProperties": false
      },
      "LearningExternalIntakeResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "mapping_state": {
            "type": "string",
            "enum": ["matched", "unmatched", "conflict"]
          },
          "status": {
            "type": "integer",
            "enum": [200, 201, 409]
          },
          "duplicate": {
            "type": "boolean"
          },
          "learning_attempt_id": {
            "type": ["string", "null"],
            "format": "uuid"
          },
          "qualification_assertion_id": {
            "type": ["string", "null"],
            "format": "uuid"
          }
        },
        "required": [
          "id",
          "mapping_state",
          "status",
          "learning_attempt_id",
          "qualification_assertion_id"
        ],
        "additionalProperties": false,
        "description": "Item status 201 new, 200 exact replay, 409 canonical fingerprint conflict. Replay/conflict never reapplies evidence. Conflict reports null target IDs and duplicate=false; exact replay has duplicate=true.",
        "allOf": [
          {
            "if": {
              "properties": {
                "status": {
                  "const": 409
                }
              },
              "required": ["status"]
            },
            "then": {
              "properties": {
                "mapping_state": {
                  "const": "conflict"
                },
                "learning_attempt_id": {
                  "type": "null"
                },
                "qualification_assertion_id": {
                  "type": "null"
                }
              }
            }
          }
        ]
      },
      "LearningExternalError": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "params": {
            "type": "object",
            "additionalProperties": {
              "type": ["string", "number", "boolean", "null"]
            }
          },
          "current": {
            "type": "object",
            "properties": {
              "revision": {
                "type": "integer",
                "minimum": 0
              }
            },
            "required": ["revision"],
            "additionalProperties": false
          }
        },
        "required": ["code", "message"],
        "additionalProperties": false
      },
      "ApiClientError": {
        "type": "object",
        "description": "Error body for API-client administration and API-client requests",
        "required": ["code", "message"],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "params": {
            "type": "object",
            "additionalProperties": true
          },
          "current": {
            "description": "Current client on a version conflict"
          }
        }
      },
      "OAuthError": {
        "type": "object",
        "description": "RFC 6749 §5.2 error body",
        "required": ["error", "error_description"],
        "properties": {
          "error": {
            "type": "string",
            "enum": [
              "invalid_request",
              "invalid_client",
              "invalid_grant",
              "unauthorized_client",
              "unsupported_grant_type",
              "unsupported_response_type",
              "invalid_scope",
              "invalid_target",
              "access_denied",
              "temporarily_unavailable"
            ]
          },
          "error_description": {
            "type": "string"
          },
          "redirect_to": {
            "type": "string",
            "description": "Authorization endpoint only: client redirect URI carrying error, error_description, state and iss; absent when the client or redirect URI is invalid (show the error to the user instead)"
          }
        }
      },
      "LearningExternalXapiRequest": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/LearningExternalXapiStatement"
          },
          {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LearningExternalXapiStatement"
            },
            "minItems": 1,
            "maxItems": 100
          }
        ]
      },
      "LearningExternalXapiStatement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "actor": {
            "$ref": "#/components/schemas/LearningExternalXapiActor"
          },
          "verb": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "enum": [
                  "http://adlnet.gov/expapi/verbs/completed",
                  "http://adlnet.gov/expapi/verbs/passed",
                  "http://adlnet.gov/expapi/verbs/failed"
                ]
              }
            },
            "required": ["id"],
            "additionalProperties": false
          },
          "object": {
            "type": "object",
            "properties": {
              "objectType": {
                "const": "Activity"
              },
              "id": {
                "$ref": "#/components/schemas/LearningExternalAbsoluteIri"
              }
            },
            "required": ["id"],
            "additionalProperties": false
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "pattern": "^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$"
          },
          "result": {
            "type": "object",
            "properties": {
              "completion": {
                "type": "boolean"
              },
              "success": {
                "type": "boolean"
              },
              "score": {
                "type": "object",
                "properties": {
                  "scaled": {
                    "type": "number",
                    "minimum": -1,
                    "maximum": 1,
                    "description": "Finite scaled score, stored as score_scaled with xapi-scaled scale; not percentage."
                  }
                },
                "required": ["scaled"],
                "additionalProperties": false
              }
            },
            "additionalProperties": false
          },
          "version": {
            "const": "1.0.3"
          }
        },
        "required": ["id", "actor", "verb", "object", "timestamp"],
        "additionalProperties": false,
        "description": "Terminal connector subset, not a full LRS. Unsupported fields including authority reject 422. Completion, pass and failure are independent facts; failed or completion=false evidence cannot complete an attempt. Assessment/pass-required offerings require passing evidence; assignment content version stays pinned. Active internal quiz, observation offering (including signed observation) or learner-only policy acknowledgement forces submitted external evidence; quiz authority uses the exact assignment-pinned offering UUID. Server raw result marks external_delivery true and delivery_language_known false with internal_evidence_required; caller cannot forge localized session/digest, source_preview, comprehension or pct-v1 credit. Matched/applied means recorded evidence, not necessarily completed training."
      },
      "LearningExternalXapiActor": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "objectType": {
                "const": "Agent"
              },
              "account": {
                "type": "object",
                "properties": {
                  "homePage": {
                    "$ref": "#/components/schemas/LearningExternalAbsoluteIri"
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  }
                },
                "required": ["homePage", "name"],
                "additionalProperties": false
              }
            },
            "required": ["account"],
            "additionalProperties": false
          },
          {
            "type": "object",
            "properties": {
              "objectType": {
                "const": "Agent"
              },
              "mbox": {
                "type": "string",
                "pattern": "^mailto:.+$",
                "description": "Lowercase mailto: prefix followed by a valid email address."
              }
            },
            "required": ["mbox"],
            "additionalProperties": false
          }
        ],
        "description": "Exactly one account or mbox Agent identity. Exact approved tenant-keyed matching only; never fuzzy name/email matching. Account names preserve literal whitespace/case bytes; mbox strips only mailto prefix and preserves mailbox case."
      },
      "LearningExternalAbsoluteIri": {
        "type": "string",
        "format": "iri",
        "pattern": "^[A-Za-z][A-Za-z0-9+.-]*:",
        "description": "Absolute IRI accepted by URL parsing, without whitespace, control characters, forbidden IRI characters or malformed percent escapes."
      },
      "LpJournalEntry": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "sequence",
          "action_id",
          "location_id",
          "settings_revision",
          "snapshot",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "sequence": {
            "type": "string",
            "pattern": "^[1-9][0-9]*$"
          },
          "action_id": {
            "type": "string",
            "format": "uuid"
          },
          "location_id": {
            "type": "string",
            "format": "uuid"
          },
          "settings_revision": {
            "type": "integer",
            "minimum": 1
          },
          "snapshot": {
            "$ref": "#/components/schemas/LpJournalSnapshot"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "LpJournalSnapshot": {
        "type": "object",
        "additionalProperties": false,
        "required": ["schema_version", "captured_at", "order", "lines", "actions", "tenders"],
        "description": "Explicit immutable allowlist of observed committed transaction view at captured_at, not reconstructed historical action-time order state; rule and camera evidence remain action-time. No PAN/processor_meta/approval_code/last4/processor_payment_id or raw action state.",
        "properties": {
          "schema_version": {
            "type": "string",
            "enum": ["butterchop.lp-journal@1"]
          },
          "captured_at": {
            "type": "string",
            "format": "date-time"
          },
          "order": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "location_id": {
                "type": "string",
                "format": "uuid"
              },
              "display_number": {
                "type": "integer"
              },
              "order_type": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "guest_count": {
                "type": "integer",
                "nullable": true,
                "description": "Actual source value; native ingest blocked when missing"
              },
              "table_number": {
                "type": "string",
                "nullable": true,
                "description": "Actual source value; native ingest blocked when missing",
                "no fabricated takeout table": null
              },
              "business_day": {
                "type": "string",
                "format": "date"
              },
              "version": {
                "type": "integer"
              },
              "subtotal": {
                "type": "string"
              },
              "tax_total": {
                "type": "string"
              },
              "tip_total": {
                "type": "string"
              },
              "total": {
                "type": "string"
              },
              "currency": {
                "type": "string"
              },
              "owner_staff_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true
              },
              "opened_by_staff_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true
              },
              "order_station_candidate_id": {
                "type": "string",
                "format": "uuid",
                "nullable": true,
                "description": "Inferred candidate only",
                "never actual action device": null
              },
              "opened_at": {
                "type": "string",
                "format": "date-time"
              },
              "closed_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "lines": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "line_no": {
                  "type": "integer"
                },
                "line_kind": {
                  "type": "string"
                },
                "menu_item_id": {
                  "type": "string",
                  "format": "uuid",
                  "nullable": true
                },
                "name_snapshot": {
                  "type": "string"
                },
                "unit_price_snapshot": {
                  "type": "string"
                },
                "qty": {
                  "type": "string"
                },
                "comp_amount": {
                  "type": "string"
                },
                "discount_amount": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "fire_state": {
                  "type": "string"
                },
                "created_at": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          },
          "actions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LpJournalAction"
            }
          },
          "tenders": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["type", "brand", "amount", "tip"],
              "properties": {
                "type": {
                  "type": "string"
                },
                "brand": {
                  "type": "string",
                  "nullable": true
                },
                "amount": {
                  "type": "string"
                },
                "tip": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "LpJournalAction": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "order_id",
          "location_id",
          "action_type",
          "amount",
          "acting_staff_id",
          "override_staff_id",
          "station_device_id",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "order_id": {
            "type": "string",
            "format": "uuid"
          },
          "location_id": {
            "type": "string",
            "format": "uuid"
          },
          "action_type": {
            "type": "string"
          },
          "amount": {
            "type": "string",
            "nullable": true
          },
          "acting_staff_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "override_staff_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "station_device_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "verified_original_order_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Only authoritative approved same-currency original-payment linkage; absent/null unknown"
          }
        }
      },
      "PartnerOrderCreateRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["external_reference", "order_type", "items"],
        "properties": {
          "external_reference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "order_type": {
            "type": "string",
            "enum": ["counter", "table", "takeout", "bar_tab", "drive_thru"]
          },
          "guest_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "guest_phone": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50
          },
          "guest_count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 999
          },
          "revenue_center_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64
          },
          "pickup": {
            "type": "object",
            "additionalProperties": false,
            "description": "Takeout only",
            "properties": {
              "scheduled_for": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64
              }
            }
          },
          "items": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["menu_item_id", "qty"],
              "properties": {
                "menu_item_id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 64
                },
                "qty": {
                  "type": "string",
                  "pattern": "^[0-9]+(\\.[0-9]{1,4})?$"
                },
                "variant_id": {
                  "type": ["string", "null"],
                  "minLength": 1,
                  "maxLength": 64
                },
                "modifiers": {
                  "type": "array",
                  "maxItems": 50,
                  "items": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": ["modifier_id"],
                    "properties": {
                      "modifier_id": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 64
                      },
                      "qty": {
                        "type": "string",
                        "pattern": "^[0-9]+(\\.[0-9]{1,4})?$"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "PartnerOrder": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "location_id",
          "status",
          "revision",
          "promised_at",
          "quoted_ready_at",
          "read_url"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "location_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string"
          },
          "revision": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Order revision as a decimal string"
          },
          "promised_at": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "Booked pickup instant of a scheduled pickup; null otherwise"
          },
          "quoted_ready_at": {
            "type": ["string", "null"],
            "format": "date-time",
            "description": "ASAP pickup estimate when the order was admitted; an estimate, not a promise"
          },
          "read_url": {
            "type": "string",
            "description": "Tenant-relative authoritative read URL of the order"
          }
        }
      },
      "PartnerOrderLookup": {
        "type": "object",
        "additionalProperties": false,
        "required": ["external_reference", "order"],
        "properties": {
          "external_reference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "order": {
            "$ref": "#/components/schemas/PartnerOrder"
          }
        }
      },
      "PartnerOrderCancelRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": ["external_reference"],
        "properties": {
          "external_reference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "reason": {
            "type": "string",
            "enum": ["guest_cancelled", "partner_cancelled", "duplicate", "other"]
          }
        }
      },
      "PartnerOrderCancel": {
        "type": "object",
        "additionalProperties": false,
        "required": ["external_reference", "state", "replayed", "order"],
        "properties": {
          "external_reference": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": ["cancelled_before_create", "voided"]
          },
          "replayed": {
            "type": "boolean"
          },
          "order": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/PartnerOrder"
              },
              {
                "type": "null"
              }
            ]
          }
        }
      },
      "PartnerDeliveryFeeEstimate": {
        "type": "object",
        "additionalProperties": false,
        "description": "Non-binding partner delivery fee estimate (gap-720). No quote_id or proof; admission recomputes the canonical quote, so revision and expiry never lock fees or delivery time.",
        "required": [
          "location_id",
          "zone_id",
          "currency",
          "fees",
          "fee_configuration",
          "total_fee_minor",
          "eligible",
          "reason_codes",
          "feasibility",
          "as_of",
          "expires_at",
          "policy_revision",
          "estimate",
          "binding"
        ],
        "properties": {
          "location_id": {
            "type": "string",
            "format": "uuid"
          },
          "zone_id": {
            "type": "string",
            "format": "uuid"
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$"
          },
          "fees": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["id", "kind", "fee_minor", "waived"],
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "kind": {
                  "type": "string",
                  "enum": ["flat", "rate", "free_above"]
                },
                "fee_minor": {
                  "type": "string",
                  "pattern": "^[0-9]+$",
                  "description": "Non-negative integer string in scale-4 minor units, like subtotal_minor"
                },
                "waived": {
                  "type": "boolean"
                }
              }
            }
          },
          "fee_configuration": {
            "type": "string",
            "enum": ["rules", "zero_fee"],
            "description": "zero_fee means the zone has no fee rules, not an inferred fee"
          },
          "total_fee_minor": {
            "type": "string",
            "pattern": "^[0-9]+$",
            "description": "Non-negative integer string in scale-4 minor units, like subtotal_minor"
          },
          "eligible": {
            "type": "boolean"
          },
          "reason_codes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "serviceability_unknown, destination_zone_mismatch, minimum_not_met, paused, delivery_disabled, or the feasibility reason code when no other reason applies"
          },
          "feasibility": {
            "type": "string",
            "enum": [
              "feasible",
              "infeasible",
              "conditionally-feasible",
              "unknown",
              "unavailable",
              "not-applicable"
            ]
          },
          "as_of": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "policy_revision": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$",
            "description": "SHA-256 of the zone, fees, partner policy and ready-time inputs"
          },
          "estimate": {
            "type": "object",
            "additionalProperties": false,
            "required": ["basis", "estimated_delivery_from", "estimated_delivery_to"],
            "properties": {
              "basis": {
                "type": "string",
                "enum": ["configured", "unknown"]
              },
              "estimated_delivery_from": {
                "type": ["string", "null"],
                "format": "date-time"
              },
              "estimated_delivery_to": {
                "type": ["string", "null"],
                "format": "date-time"
              }
            }
          },
          "binding": {
            "type": "string",
            "const": "non_binding_estimate"
          }
        }
      },
      "NutritionWebhookVersion": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "subject_id": {
            "type": "string",
            "format": "uuid"
          },
          "source_kind": {
            "$ref": "#/components/schemas/NutritionWebhookSourceKind"
          },
          "revision": {
            "$ref": "#/components/schemas/NutritionWebhookRevision"
          },
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "state": {
            "type": "string",
            "enum": ["approved", "invalidated", "withdrawn"]
          },
          "digest": {
            "$ref": "#/components/schemas/NutritionWebhookDigest"
          },
          "effective_at": {
            "type": "string",
            "format": "date-time",
            "description": "Database-clock timestamp."
          },
          "resource_url": {
            "type": "string",
            "format": "uri-reference",
            "description": "Tenant/location-authorized /v1/menu/nutrition-versions/{subject_id}; source_kind=guest_nutrition_projection query selects guest location owner; omitted source_kind defaults to menu_labeling_release."
          },
          "tombstone": {
            "type": "boolean"
          },
          "projection": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/NutritionWebhookCalorieProjection"
              },
              {
                "$ref": "#/components/schemas/NutritionWebhookGuestProjection"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "subject_id",
          "source_kind",
          "revision",
          "version",
          "state",
          "digest",
          "effective_at",
          "resource_url",
          "tombstone",
          "projection"
        ],
        "description": "Authoritative current version, not historical last-approved data. revision is per (org,source_kind,subject_id); version is the integer owner source version. Source versions never regress; invalidated/withdrawn cannot return to approved within the same source version, and withdrawn is terminal for that version. Invalidated/withdrawn returns tombstone=true and projection=null, never a prior current value. Consumers must fetch this resource before applying and compare revision; webhook2xx is received, not applied. Reads recheck actual owner lifecycle and effective/expiry windows against the database; expired/stale public authority returns an invalidated tombstone even if cached nutrition_current remains approved. Exact tenant/location owner context pins the reviewed menu labeling release and profile version, or exact guest publication UUID; namespace/type/reviewer flags alone are insufficient. Internal release/profile/publication IDs never appear in the minimal public envelope. No legacy source-kind alias is accepted.",
        "oneOf": [
          {
            "properties": {
              "source_kind": {
                "const": "menu_labeling_release"
              },
              "state": {
                "const": "approved"
              },
              "tombstone": {
                "const": false
              },
              "projection": {
                "$ref": "#/components/schemas/NutritionWebhookCalorieProjection"
              }
            }
          },
          {
            "properties": {
              "source_kind": {
                "const": "guest_nutrition_projection"
              },
              "state": {
                "const": "approved"
              },
              "tombstone": {
                "const": false
              },
              "projection": {
                "$ref": "#/components/schemas/NutritionWebhookGuestProjection"
              }
            }
          },
          {
            "properties": {
              "state": {
                "enum": ["invalidated", "withdrawn"]
              },
              "tombstone": {
                "const": true
              },
              "projection": {
                "type": "null"
              }
            }
          }
        ]
      },
      "NutritionWebhookSourceKind": {
        "type": "string",
        "enum": ["menu_labeling_release", "guest_nutrition_projection"]
      },
      "NutritionWebhookRevision": {
        "type": "string",
        "pattern": "^[1-9][0-9]*$",
        "description": "Monotonic per-owner subject revision serialized as a decimal string, never a JavaScript number."
      },
      "NutritionWebhookDigest": {
        "type": "string",
        "pattern": "^[0-9a-f]{64}$"
      },
      "NutritionWebhookCalorieProjection": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "kind": {
            "const": "menu_calorie_labels"
          },
          "applicability": {
            "type": "string",
            "enum": ["covered", "exempt", "voluntary", "unknown"]
          },
          "rounding_rule": {
            "type": "string"
          },
          "option_policy": {
            "type": "string"
          },
          "required_statement": {
            "type": "string"
          },
          "preview_digest": {
            "$ref": "#/components/schemas/NutritionWebhookDigest"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NutritionWebhookCalorieItem"
            }
          }
        },
        "required": ["items"],
        "description": "Exact display whitelist from menu_labeling_release owner menu_calorie_label / butterchop.menu_labeling. Display keys are copied only when present. Never recipe components, supplier documents, raw_kcal, supplemental_nutrition_ref, approval/evidence/private references. Staff-only recipe-calculation approval is not public approval. Exact tenant/location owner context pins the reviewed menu labeling release and profile version, or exact guest publication UUID; namespace/type/reviewer flags alone are insufficient. Internal release/profile/publication IDs never appear in the minimal public envelope. No legacy source-kind alias is accepted."
      },
      "NutritionWebhookCalorieItem": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "menu_item_id": {
            "type": "string",
            "format": "uuid"
          },
          "display_text": {
            "type": "string"
          },
          "rounded_kcal": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "min": {
                "type": "number"
              },
              "max": {
                "type": "number"
              }
            },
            "required": ["min", "max"]
          },
          "display_policy": {
            "type": "string",
            "enum": ["standard", "range", "per_option"]
          },
          "serving_basis": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NutritionWebhookCalorieOption"
            }
          }
        },
        "required": [
          "menu_item_id",
          "display_text",
          "rounded_kcal",
          "display_policy",
          "serving_basis",
          "options"
        ]
      },
      "NutritionWebhookCalorieOption": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "option_ids": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "rounded_kcal": {
            "type": "number"
          }
        },
        "required": ["option_ids", "rounded_kcal"]
      },
      "NutritionWebhookGuestProjection": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "menu_revision": {
            "type": "string"
          },
          "publication_revision": {
            "type": "integer",
            "minimum": 1
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NutritionWebhookGuestItem"
            }
          },
          "as_of": {
            "type": "string",
            "format": "date-time",
            "description": "Database-clock timestamp."
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Database-clock timestamp."
          }
        },
        "required": ["menu_revision", "publication_revision", "items", "as_of", "expires_at"],
        "description": "Exact public whitelist from migration000144 commerce.menu_nutrition_publications approved current snapshot, enriched with row menu_revision/publication_revision/as_of/expires_at. Canonical subject is location_id. Excludes binding revisions, recipe inputs, supplier documents and all private source/approval references; only explicit owner transitions produce public events."
      },
      "NutritionWebhookGuestItem": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "item_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NutritionWebhookGuestOption"
            }
          },
          "serving_basis": {
            "$ref": "#/components/schemas/NutritionWebhookGuestServingBasis"
          },
          "nutrients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NutritionWebhookGuestNutrient"
            }
          },
          "attributes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/NutritionWebhookGuestAttribute"
            }
          },
          "unknown_reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "item_id",
          "name",
          "options",
          "serving_basis",
          "nutrients",
          "attributes",
          "unknown_reasons"
        ]
      },
      "NutritionWebhookGuestOption": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "option_id": {
            "type": "string",
            "format": "uuid"
          },
          "operation": {
            "type": "string"
          }
        },
        "required": ["option_id", "operation"]
      },
      "NutritionWebhookGuestServingBasis": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "quantity": {
            "type": "number"
          },
          "portion_mass_g": {
            "type": "string"
          },
          "notice": {
            "type": "string"
          }
        },
        "required": ["quantity", "portion_mass_g", "notice"]
      },
      "NutritionWebhookGuestNutrient": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "energy_kcal",
              "total_fat",
              "saturated_fat",
              "trans_fat",
              "cholesterol",
              "sodium",
              "total_carbohydrate",
              "dietary_fiber",
              "total_sugars",
              "added_sugars",
              "protein",
              "vitamin_d",
              "calcium",
              "iron",
              "potassium"
            ]
          },
          "unit": {
            "type": "string"
          },
          "value": {
            "type": ["string", "null"],
            "description": "Exact decimal string when known; null when unknown, never zero or a partial sum."
          },
          "state": {
            "type": "string",
            "enum": ["known", "unknown"]
          },
          "unknown_reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["code", "unit", "value", "state", "unknown_reasons"]
      },
      "NutritionWebhookGuestAttribute": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "vocabulary_key": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": ["allergen", "diet"]
          },
          "term": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "cross_contact": {
            "type": "string",
            "description": "Qualified kitchen cross-contact wording, independent of ingredient state; no safety inference."
          }
        },
        "required": ["vocabulary_key", "kind", "term", "state", "label", "cross_contact"]
      },
      "NutritionWebhookError": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "params": {
            "type": "object",
            "additionalProperties": {
              "type": ["string", "number", "boolean", "null"]
            }
          },
          "current": {}
        },
        "required": ["code", "message"],
        "description": "AppError envelope; current may carry current revision or sanitized validation issues, never raw provider bodies or secrets."
      },
      "WarehouseDelivery": {
        "type": "object",
        "required": [
          "id",
          "subscription_id",
          "generation_id",
          "sequence",
          "cursor_from",
          "cursor_to",
          "row_count",
          "tombstone_count",
          "files",
          "manifest_key",
          "started_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "subscription_id": {
            "type": "string",
            "format": "uuid"
          },
          "generation_id": {
            "type": "string",
            "format": "uuid"
          },
          "sequence": {
            "type": "string",
            "pattern": "^[0-9]+$"
          },
          "cursor_from": {
            "type": "object",
            "additionalProperties": true
          },
          "cursor_to": {
            "type": "object",
            "additionalProperties": true
          },
          "row_count": {
            "type": "string",
            "pattern": "^[0-9]+$"
          },
          "tombstone_count": {
            "type": "string",
            "pattern": "^[0-9]+$"
          },
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WarehouseFile"
            }
          },
          "manifest_key": {
            "type": "string"
          },
          "started_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WarehouseFile": {
        "type": "object",
        "required": ["key", "bytes", "sha256", "row_count"],
        "properties": {
          "key": {
            "type": "string"
          },
          "bytes": {
            "type": "integer",
            "minimum": 0,
            "maximum": 268435456,
            "description": "Compressed byte length"
          },
          "sha256": {
            "type": "string",
            "pattern": "^[0-9a-f]{64}$"
          },
          "row_count": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "WarehouseFileUrl": {
        "type": "object",
        "required": ["url", "expires_in"],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "expires_in": {
            "type": "integer",
            "const": 900
          }
        }
      },
      "FoodSafetyExportView": {
        "type": "object",
        "required": [
          "export_id",
          "location_id",
          "from",
          "to",
          "timezone",
          "format",
          "redaction_profile",
          "state",
          "state_reason",
          "quality",
          "created_at",
          "updated_at",
          "render_attempts",
          "manifest",
          "document",
          "download_available",
          "warnings"
        ],
        "properties": {
          "export_id": {
            "type": "string",
            "format": "uuid"
          },
          "location_id": {
            "type": "string",
            "format": "uuid"
          },
          "from": {
            "type": "string",
            "format": "date"
          },
          "to": {
            "type": "string",
            "format": "date"
          },
          "timezone": {
            "type": "string"
          },
          "format": {
            "type": "string",
            "enum": ["pdf"]
          },
          "redaction_profile": {
            "type": "string",
            "enum": ["internal", "inspector"]
          },
          "state": {
            "$ref": "#/components/schemas/FoodSafetyExportState"
          },
          "state_reason": {
            "type": ["string", "null"]
          },
          "quality": {
            "type": ["string", "null"],
            "enum": ["complete", "partial", null]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "render_attempts": {
            "type": "integer"
          },
          "manifest": {
            "type": "object",
            "required": ["schema", "manifest_sha256", "frozen_at", "counts"],
            "properties": {
              "schema": {
                "type": "string",
                "const": "foodsafety.export.v1"
              },
              "manifest_sha256": {
                "type": "string",
                "pattern": "^[0-9a-f]{64}$"
              },
              "frozen_at": {
                "type": "string",
                "format": "date-time"
              },
              "counts": {
                "$ref": "#/components/schemas/FoodSafetyExportCounts"
              }
            }
          },
          "document": {
            "type": ["object", "null"],
            "required": ["document_id", "page_count"],
            "properties": {
              "document_id": {
                "type": "string",
                "format": "uuid"
              },
              "page_count": {
                "type": ["integer", "null"]
              }
            }
          },
          "download_available": {
            "type": "boolean"
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "FoodSafetyExportState": {
        "type": "string",
        "enum": ["queued", "rendered", "failed", "partial"]
      },
      "FoodSafetyExportCounts": {
        "type": "object",
        "required": [
          "temperature_logs",
          "temperature_failed",
          "temperature_no_target",
          "temperature_amended",
          "checklist_items",
          "checklist_failed",
          "checklist_unknown",
          "missing",
          "corrective_open",
          "corrective_closed",
          "corrective_action_recorded",
          "signoffs",
          "signoffs_amended",
          "evidence"
        ],
        "properties": {
          "temperature_logs": {
            "type": "integer"
          },
          "temperature_failed": {
            "type": "integer"
          },
          "temperature_no_target": {
            "type": "integer"
          },
          "temperature_amended": {
            "type": "integer"
          },
          "checklist_items": {
            "type": "integer"
          },
          "checklist_failed": {
            "type": "integer"
          },
          "checklist_unknown": {
            "type": "integer"
          },
          "missing": {
            "type": "integer"
          },
          "corrective_open": {
            "type": "integer"
          },
          "corrective_closed": {
            "type": "integer"
          },
          "corrective_action_recorded": {
            "type": "integer"
          },
          "signoffs": {
            "type": "integer"
          },
          "signoffs_amended": {
            "type": "integer"
          },
          "evidence": {
            "type": "integer"
          }
        }
      },
      "FoodSafetyExportError": {
        "type": "object",
        "required": ["code", "message"],
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "params": {
            "type": "object",
            "additionalProperties": true
          },
          "current": {
            "description": "Current snapshot state on 409 (e.g. {state})"
          }
        }
      },
      "McpJsonRpcMessage": {
        "type": "object",
        "description": "One JSON-RPC 2.0 request (id + method), notification (method, no id) or client response. MCP methods: initialize {protocolVersion, capabilities, clientInfo}, ping, tools/list, tools/call {name, arguments}.",
        "required": ["jsonrpc"],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": ["2.0"]
          },
          "id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ]
          },
          "method": {
            "type": "string"
          },
          "params": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "McpJsonRpcResponse": {
        "type": "object",
        "required": ["jsonrpc", "id"],
        "properties": {
          "jsonrpc": {
            "type": "string",
            "enum": ["2.0"]
          },
          "id": {
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "integer"
              }
            ],
            "nullable": true
          },
          "result": {
            "type": "object",
            "additionalProperties": true,
            "description": "initialize: {protocolVersion, capabilities.tools, serverInfo, instructions}; tools/list: {tools[]: name, title, description, inputSchema, annotations.readOnlyHint=true}; tools/call: {content[], structuredContent (report money strings, currency, quality_state complete|partial|no_data, citation {metric, period, location_id, source_path, freshness, quality_state}), isError}."
          },
          "error": {
            "type": "object",
            "required": ["code", "message"],
            "properties": {
              "code": {
                "type": "integer",
                "description": "-32700 parse, -32600 invalid request, -32601 method not found, -32602 invalid params"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "headers": {
      "RateLimitLimit": {
        "description": "Limit of the binding (lowest-remaining) window for this API client",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitRemaining": {
        "description": "Requests remaining in the binding window",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitReset": {
        "description": "Seconds until the binding window resets",
        "schema": {
          "type": "integer"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "RateLimited": {
        "description": "Per-client rate limit exceeded (token bucket shared across replicas; defaults 120 requests/minute and 10,000/day, lowerable per client). API requests return {code: rate_limited, message}; the token endpoint returns {error: temporarily_unavailable, error_description}.",
        "headers": {
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/ApiClientError"
                },
                {
                  "$ref": "#/components/schemas/OAuthError"
                }
              ]
            }
          }
        }
      },
      "RateLimitUnavailable": {
        "description": "The shared rate-limit store is unavailable; API-client requests and token issuance fail closed. API requests return {code: rate_limit_unavailable, message} with Retry-After 5; the token endpoint returns {error: temporarily_unavailable, error_description}.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/ApiClientError"
                },
                {
                  "$ref": "#/components/schemas/OAuthError"
                }
              ]
            }
          }
        }
      },
      "WarehouseError": {
        "description": "Warehouse error (400 invalid input,403 scope,404 tenant/resource,409 conflict with current,422 grant/unsupported storage,428 version,502 real storage failure)",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      }
    },
    "securitySchemes": {
      "externalBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Opaque API access token or API key in Authorization: Bearer. Staff session JWTs are not interchangeable. Delegated-only actions require a public PKCE client."
      }
    }
  }
}
