{
  "openapi": "3.0.3",
  "info": {
    "title": "QRScanInk API",
    "version": "1.0.0",
    "description": "Practical contract for QRScanInk public, auth, core, admin, AI, and MCP endpoints."
  },
  "servers": [
    {"url": "https://api.qrscan.ink/api"},
    {"url": "https://api.qrscanink.test/api"}
  ],
  "security": [{"bearerAuth": []}],
  "components": {
    "securitySchemes": {
      "bearerAuth": {"type": "http", "scheme": "bearer"},
      "publicRcaptcha": {"type": "apiKey", "in": "header", "name": "X-QRScanInk-rCAPTCHA"}
    },
    "schemas": {
      "Error": {"type": "object", "properties": {"message": {"type": "string"}, "errors": {"type": "object"}}},
      "Paginator": {"type": "object", "properties": {"data": {"type": "array", "items": {}}, "current_page": {"type": "integer"}, "per_page": {"type": "integer"}, "total": {"type": "integer"}}},
      "Business": {"type": "object", "properties": {"id": {"type": "integer"}, "name": {"type": "string"}, "type": {"type": "string"}}},
      "QrLink": {"type": "object", "properties": {"id": {"type": "integer"}, "business_id": {"type": "integer"}, "slug_display": {"type": "string"}, "status": {"type": "string"}}}
    },
    "responses": {
      "Unauthorized": {"description": "Missing or invalid session/token."},
      "Forbidden": {"description": "Scope, business restriction, or ownership denied."},
      "RateLimited": {"description": "Named throttle exceeded."},
      "ValidationError": {"description": "Request failed validation."}
    }
  },
  "x-rate-limits": {
    "auth": "8/minute",
    "rcaptcha": "20/minute",
    "public_forms": "12/minute",
    "go_redirects": "240/minute",
    "api_user": "120/minute",
    "api_token": "token configured, default 120/minute",
    "mcp": "60/minute",
    "ai": "30/minute",
    "admin": "90/minute",
    "exports": "20/minute",
    "webhook_tests": "10/minute"
  },
  "paths": {
    "/public/rcaptcha/challenge": {"post": {"tags": ["public"], "security": [], "responses": {"201": {"description": "Challenge created"}, "429": {"$ref": "#/components/responses/RateLimited"}}}},
    "/public/rcaptcha/verify": {"post": {"tags": ["public"], "security": [], "responses": {"200": {"description": "One-use verification token"}, "422": {"$ref": "#/components/responses/ValidationError"}}}},
    "/public/lead-submissions": {"post": {"tags": ["public"], "security": [{"publicRcaptcha": []}], "responses": {"201": {"description": "Lead submitted"}, "422": {"$ref": "#/components/responses/ValidationError"}}}},
    "/public/restaurant/service-requests": {"post": {"tags": ["public"], "security": [{"publicRcaptcha": []}], "responses": {"201": {"description": "Public table service request submitted"}}}},
    "/public/restaurant/order-intents": {"post": {"tags": ["public"], "security": [{"publicRcaptcha": []}], "responses": {"201": {"description": "Public request-only restaurant order intent submitted"}}}},
    "/auth/widget/send-magic-link": {"post": {"tags": ["auth"], "security": [], "responses": {"200": {"description": "Magic link sent"}}}},
    "/auth/magicauth/complete": {"post": {"tags": ["auth"], "security": [], "responses": {"200": {"description": "API session issued"}}}},
    "/businesses": {"get": {"tags": ["core"], "responses": {"200": {"description": "Paginated businesses"}}}, "post": {"tags": ["core"], "responses": {"201": {"description": "Business created"}}}},
    "/qr-links": {"get": {"tags": ["core"], "responses": {"200": {"description": "Paginated QR links"}}}, "post": {"tags": ["core"], "responses": {"201": {"description": "QR link created"}}}},
    "/qr-links/check-slug": {"get": {"tags": ["core"], "responses": {"200": {"description": "Slug availability"}}}},
    "/menus": {"get": {"tags": ["core"], "responses": {"200": {"description": "Paginated menus"}}}, "post": {"tags": ["core"], "responses": {"201": {"description": "Menu created"}}}},
    "/landing-pages": {"get": {"tags": ["core"], "responses": {"200": {"description": "Paginated landing pages"}}}, "post": {"tags": ["core"], "responses": {"201": {"description": "Landing page created"}}}},
    "/campaigns": {"get": {"tags": ["core"], "responses": {"200": {"description": "Paginated campaigns"}}}, "post": {"tags": ["core"], "responses": {"201": {"description": "Campaign created"}}}},
    "/smart-rules": {"get": {"tags": ["core"], "responses": {"200": {"description": "Paginated smart rules"}}}, "post": {"tags": ["core"], "responses": {"201": {"description": "Smart rule created"}}}},
    "/lead-forms": {"get": {"tags": ["core"], "responses": {"200": {"description": "Paginated lead forms"}}}, "post": {"tags": ["core"], "responses": {"201": {"description": "Lead form created"}}}},
    "/analytics/summary": {"get": {"tags": ["analytics"], "responses": {"200": {"description": "Bounded account/business analytics summary"}}}},
    "/analytics/aggregate": {"get": {"tags": ["analytics"], "parameters": [{"name": "group_by", "in": "query", "schema": {"type": "string", "enum": ["day", "hour", "device", "country", "region", "city", "placement", "campaign", "content_type", "destination_mode"]}}], "responses": {"200": {"description": "Database-grouped analytics aggregate"}}}},
    "/integration-guides": {"get": {"tags": ["integrations"], "responses": {"200": {"description": "Client integration guide catalog with setup fields and tenant credential status"}}}},
    "/integration-credentials": {"get": {"tags": ["integrations"], "responses": {"200": {"description": "Paginated masked tenant integration credentials"}}}, "post": {"tags": ["integrations"], "responses": {"201": {"description": "Tenant integration credential created or updated with masked fields"}}}},
    "/integration-credentials/{tenantIntegrationCredential}": {"patch": {"tags": ["integrations"], "responses": {"200": {"description": "Tenant integration credential updated"}}}, "delete": {"tags": ["integrations"], "responses": {"200": {"description": "Tenant integration credential revoked/deleted"}}}},
    "/integrations/{key}/sample-event": {"post": {"tags": ["integrations"], "responses": {"201": {"description": "Sample scan, lead, report, service, order, recall, passport, or widget event delivered or logged"}}}},
    "/integration-deliveries": {"get": {"tags": ["integrations"], "responses": {"200": {"description": "Paginated redacted tenant integration delivery logs"}}}},
    "/integration-deliveries/{tenantIntegrationDelivery}/retry": {"post": {"tags": ["integrations"], "responses": {"200": {"description": "Tenant integration delivery retried with signed payload"}}}},
    "/integration-recipes": {"get": {"tags": ["integrations"], "responses": {"200": {"description": "No-code and vertical integration recipes"}}}},
    "/integration-recipes/{key}/install": {"post": {"tags": ["integrations"], "responses": {"201": {"description": "Integration recipe installed for a business workspace"}}}},
    "/workflows/restaurant-launch": {"post": {"tags": ["workflows"], "responses": {"201": {"description": "Creates business/menu/menu QR/table pack/tables/meal periods/scan alerts/AI task in one transaction"}}}},
    "/workflows/product-passport-launch": {"post": {"tags": ["workflows"], "responses": {"201": {"description": "Creates product, batch, passport QR, optional assets, and scan alerts in one transaction"}}}},
    "/workflows/agency-client-launch": {"post": {"tags": ["workflows"], "responses": {"201": {"description": "Creates client business, client space, starter QR, invite, report schedule, report, and widget config"}}}},
    "/integrations/{key}/test": {"post": {"tags": ["integrations"], "responses": {"200": {"description": "Credential-gated integration test result"}, "422": {"$ref": "#/components/responses/ValidationError"}}}},
    "/bulk/qr-links/preview": {"post": {"tags": ["bulk"], "responses": {"200": {"description": "CSV QR import validation preview"}, "422": {"$ref": "#/components/responses/ValidationError"}}}},
    "/bulk/qr-links/import": {"post": {"tags": ["bulk"], "responses": {"201": {"description": "Validated CSV QR links imported"}, "422": {"description": "Preview rows contain validation errors"}}}},
    "/exports/bundles": {"get": {"tags": ["exports"], "responses": {"200": {"description": "Export bundle metadata, formats, endpoints, and caps"}}}},
    "/reports": {"get": {"tags": ["reports"], "responses": {"200": {"description": "Paginated reports"}}}, "post": {"tags": ["reports"], "responses": {"201": {"description": "Report generated"}}}},
    "/reports/schedules": {"get": {"tags": ["reports"], "responses": {"200": {"description": "Paginated report schedules"}}}, "post": {"tags": ["reports"], "responses": {"201": {"description": "Report schedule created"}}}},
    "/reports/bundles": {"get": {"tags": ["reports"], "responses": {"200": {"description": "Grouped client report bundles"}}}, "post": {"tags": ["reports"], "responses": {"201": {"description": "Agency/client report bundle generated"}}}},
    "/reports/schedules/{reportSchedule}": {"patch": {"tags": ["reports"], "responses": {"200": {"description": "Report schedule updated"}}}, "delete": {"tags": ["reports"], "responses": {"200": {"description": "Report schedule deleted"}}}},
    "/webhooks": {"post": {"tags": ["integrations"], "responses": {"201": {"description": "HTTPS webhook created"}}}},
    "/integrations/webhooks/test": {"post": {"tags": ["integrations"], "responses": {"200": {"description": "Webhook test sent"}}}},
    "/ai/summary": {"get": {"tags": ["ai"], "responses": {"200": {"description": "Account AI summary"}}}},
    "/ai/analyze-link": {"post": {"tags": ["ai"], "responses": {"200": {"description": "QR link audit"}}}},
    "/mcp/tools": {"get": {"tags": ["mcp"], "responses": {"200": {"description": "Tool catalog"}}}},
    "/mcp/context": {"get": {"tags": ["mcp"], "responses": {"200": {"description": "Scoped account context"}}}},
    "/mcp/execute": {"post": {"tags": ["mcp"], "responses": {"200": {"description": "Tool result"}, "403": {"$ref": "#/components/responses/Forbidden"}}}},
    "/admin/credential-health": {"get": {"tags": ["admin"], "responses": {"200": {"description": "Masked credential health"}}}},
    "/admin/audit-logs": {"get": {"tags": ["admin"], "responses": {"200": {"description": "Paginated audit logs"}}}},
    "/pricing-policy": {"get": {"tags": ["core"], "responses": {"200": {"description": "Pricing limits and cancellation-safe QR policy"}}}},
    "/wallet-passes": {"get": {"tags": ["wallet"], "responses": {"200": {"description": "Paginated wallet passes"}}}, "post": {"tags": ["wallet"], "responses": {"201": {"description": "Wallet pass created"}}}},
    "/wallet-passes/{walletPass}/export": {"get": {"tags": ["wallet"], "responses": {"200": {"description": "WalletCard fallback export or native adapter credential status"}}}},
    "/wallet-passes/{walletPass}/public-preview": {"get": {"tags": ["wallet"], "responses": {"200": {"description": "WalletCard mobile pass preview payload"}}}},
    "/gs1/validate": {"post": {"tags": ["product-passports"], "responses": {"200": {"description": "GS1 Digital Link validation and URI builder"}}}},
    "/product-passports": {"get": {"tags": ["product-passports"], "responses": {"200": {"description": "Paginated product passports"}}}, "post": {"tags": ["product-passports"], "responses": {"201": {"description": "Product passport created"}}}},
    "/scan-notification-preferences": {"get": {"tags": ["analytics"], "responses": {"200": {"description": "Paginated scan alert preferences"}}}, "post": {"tags": ["analytics"], "responses": {"201": {"description": "Scan alert preference saved"}}}},
    "/table-qr-packs": {"get": {"tags": ["restaurants"], "responses": {"200": {"description": "Paginated table QR packs"}}}, "post": {"tags": ["restaurants"], "responses": {"201": {"description": "Table QR pack created"}}}},
    "/restaurant/tables": {"get": {"tags": ["restaurants"], "responses": {"200": {"description": "Paginated restaurant tables"}}}, "post": {"tags": ["restaurants"], "responses": {"201": {"description": "Table created with optional QR assignment"}}}},
    "/restaurant/service-requests": {"get": {"tags": ["restaurants"], "responses": {"200": {"description": "Paginated service requests"}}}, "post": {"tags": ["restaurants"], "responses": {"201": {"description": "Service request created"}}}},
    "/restaurant/order-intents": {"get": {"tags": ["restaurants"], "responses": {"200": {"description": "Paginated order intents"}}}, "post": {"tags": ["restaurants"], "responses": {"201": {"description": "Order intent created for request-only or future payment flows"}}}},
    "/restaurant/order-intents/{orderIntent}/ticket": {"get": {"tags": ["restaurants"], "responses": {"200": {"description": "Printable kitchen ticket HTML or CSV"}}}},
    "/restaurant/order-intents/{orderIntent}/advance": {"post": {"tags": ["restaurants"], "responses": {"200": {"description": "Order intent status advanced with history"}}}},
    "/restaurant/kitchen-queue": {"get": {"tags": ["restaurants"], "responses": {"200": {"description": "Open order intents and service requests for kitchen/staff queue"}}}},
    "/restaurant/pos-handoff": {"get": {"tags": ["restaurants"], "responses": {"200": {"description": "Request-only POS handoff JSON or CSV export"}}}},
    "/restaurant/meal-periods": {"get": {"tags": ["restaurants"], "responses": {"200": {"description": "Paginated meal periods"}}}, "post": {"tags": ["restaurants"], "responses": {"201": {"description": "Meal period created"}}}},
    "/products": {"get": {"tags": ["product-passports"], "responses": {"200": {"description": "Paginated products"}}}, "post": {"tags": ["product-passports"], "responses": {"201": {"description": "Product created"}}}},
    "/product-batches": {"get": {"tags": ["product-passports"], "responses": {"200": {"description": "Paginated product batches"}}}, "post": {"tags": ["product-passports"], "responses": {"201": {"description": "Product batch created"}}}},
    "/product-passports/bulk-import": {"post": {"tags": ["product-passports"], "responses": {"201": {"description": "Product passports imported from validated CSV"}}}},
    "/product-passports/{productPassport}/resolver-links": {"patch": {"tags": ["product-passports"], "responses": {"200": {"description": "Resolver destinations updated"}}}},
    "/product-passports/{productPassport}/recall-notice": {"post": {"tags": ["product-passports"], "responses": {"200": {"description": "Recall notice published"}}}},
    "/product-passports/{productPassport}/recall-override": {"post": {"tags": ["product-passports"], "responses": {"200": {"description": "Recall override published and QR destination updated"}}}},
    "/product-passports/{productPassport}/exports": {"get": {"tags": ["product-passports"], "responses": {"200": {"description": "DPP JSON-LD, EPCIS-style, CSV, or PDF export"}}}},
    "/product-passports/{productPassport}/analytics": {"get": {"tags": ["product-passports"], "responses": {"200": {"description": "Product and batch scan analytics"}}}},
    "/assets": {"get": {"tags": ["agency"], "responses": {"200": {"description": "Paginated asset library"}}}, "post": {"tags": ["agency"], "responses": {"201": {"description": "Asset uploaded"}}}},
    "/team-invites": {"get": {"tags": ["agency"], "responses": {"200": {"description": "Paginated team invites"}}}, "post": {"tags": ["agency"], "responses": {"201": {"description": "Team invite created"}}}},
    "/team-invites/accept": {"post": {"tags": ["agency"], "responses": {"200": {"description": "Authenticated invited user accepts team access"}}}},
    "/client-spaces": {"get": {"tags": ["agency"], "responses": {"200": {"description": "Paginated client spaces"}}}, "post": {"tags": ["agency"], "responses": {"201": {"description": "Client space created"}}}},
    "/notifications": {"get": {"tags": ["notifications"], "responses": {"200": {"description": "Paginated dashboard notifications"}}}},
    "/push/config": {"get": {"tags": ["notifications"], "responses": {"200": {"description": "QRScanInk Pulse browser push public config"}}}},
    "/push/subscriptions": {"get": {"tags": ["notifications"], "responses": {"200": {"description": "Paginated Pulse device subscriptions"}}}, "post": {"tags": ["notifications"], "responses": {"201": {"description": "Pulse device subscription saved"}}}},
    "/push/test": {"post": {"tags": ["notifications"], "responses": {"200": {"description": "Pulse test notification queued"}}}},
    "/notification-preferences": {"patch": {"tags": ["notifications"], "responses": {"200": {"description": "Notification preferences updated"}}}},
    "/widget/config": {"get": {"tags": ["widget"], "security": [], "responses": {"200": {"description": "Public widget config"}}}, "post": {"tags": ["widget"], "responses": {"201": {"description": "Widget config created"}}}},
    "/widget/lead": {"post": {"tags": ["widget"], "security": [], "responses": {"201": {"description": "Widget lead captured"}}}},
    "/custom-domains/{customDomain}/health": {"get": {"tags": ["domains"], "responses": {"200": {"description": "Custom-domain verification and certificate health"}}}},
    "/reports/{report}/preview": {"get": {"tags": ["reports"], "responses": {"200": {"description": "Report preview payload"}}}},
    "/reports/schedules/{reportSchedule}/send-test": {"post": {"tags": ["reports"], "responses": {"200": {"description": "Report schedule test notification queued"}}}},
    "/qr-links/{qrLink}/safety-report": {"get": {"tags": ["safety"], "responses": {"200": {"description": "Scannability and quishing-safe report"}}}},
    "/ai/menu-imports": {"get": {"tags": ["ai"], "responses": {"200": {"description": "Paginated AI menu imports awaiting approval"}}}},
    "/ai/menu-imports/{aiMenuImport}/approve": {"post": {"tags": ["ai"], "responses": {"200": {"description": "AI menu import approved into draft menu"}}}}
  }
}
