{
  "openapi": "3.0.3",
  "info": {
    "title": "CBMS Partner API",
    "version": "1.0.0",
    "description": "Central Booking Management System — Partner API for venue/resource discovery, availability, two-phase hold/confirm booking, cancellation, idempotent retries, and signed webhooks.\n\nThe Partner API is /api/v1. Additive, backward-compatible changes (new optional fields, new endpoints, new webhook event types) ship in v1; ignore unknown fields. A breaking change (removing/renaming a field, changing a field meaning or type, changing required parameters) requires a new version prefix, never a silent change to v1. Deprecated behaviour is announced in docs/API_CHANGELOG.md with a transition period before removal.\n\nHuman integration guide: docs/PARTNER_API.md. Changelog: docs/API_CHANGELOG.md.",
    "contact": {
      "name": "CBMS Platform Team",
      "url": "https://cbms.venuesetu.com"
    },
    "x-api-version": "v1",
    "x-versioning-policy": "additive-in-v1",
    "x-changelog": "docs/API_CHANGELOG.md"
  },
  "servers": [
    {
      "url": "https://stage.cbms.venuesetu.com/api/v1",
      "description": "Sandbox — recommended for integration. Same API as production; isolated credentials. Unauthenticated GET /health reports {\"sandbox\": true}."
    },
    {
      "url": "https://cbms.venuesetu.com/api/v1",
      "description": "Production — use only after certification, with production credentials. GET /health reports {\"sandbox\": false}."
    },
    {
      "url": "http://localhost:3000/api/v1",
      "description": "Local development"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Booking",
      "description": "Availability, holds, confirm, cancel, refund"
    },
    {
      "name": "Venues",
      "description": "Authorized venue and resource discovery"
    },
    {
      "name": "Packages",
      "description": "Prepaid credit bundles"
    },
    {
      "name": "Waitlist",
      "description": "Join/list/cancel waitlist entries for a sold-out slot"
    },
    {
      "name": "Webhooks",
      "description": "Subscriptions, signing, delivery observability"
    },
    {
      "name": "Contract",
      "description": "This OpenAPI document"
    }
  ],
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Partner API key. Opaque hex issued once at creation (no pk_live_ / pk_test_ prefix). Identity, venue authorization, rate limiting, and booking ownership all come from this key — there is no request field that selects a different partner. Sandbox keys and production keys are unrelated credential spaces; never send a production key to the sandbox host or the reverse."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Stable machine-readable code, e.g. SLOT_NOT_AVAILABLE, UNAUTHORIZED, VENUE_NOT_AUTHORIZED."
          },
          "message": {
            "type": "string"
          },
          "request_id": {
            "type": "string",
            "description": "Echo of X-Request-Id. Present on most error responses."
          },
          "details": {
            "description": "Optional context. Validation failures (error=VALIDATION_ERROR) return an array of {field, message, in}."
          }
        }
      },
      "AvailabilitySlot": {
        "type": "object",
        "properties": {
          "slot_id": {
            "type": "string",
            "format": "uuid"
          },
          "resource_id": {
            "type": "string",
            "example": "badminton-court-1"
          },
          "slot_start": {
            "type": "string",
            "format": "date-time"
          },
          "slot_end": {
            "type": "string",
            "format": "date-time"
          },
          "price_rupees": {
            "type": "integer"
          },
          "is_available": {
            "type": "boolean",
            "description": "Hint only. A true value is not a reservation — hold is the mutual-exclusion gate."
          }
        }
      },
      "CreateHoldRequest": {
        "type": "object",
        "required": [
          "venue_id",
          "resource_id",
          "slot_start",
          "slot_duration_minutes",
          "idempotency_key"
        ],
        "properties": {
          "venue_id": {
            "type": "string",
            "format": "uuid"
          },
          "resource_id": {
            "type": "string",
            "description": "Copy from GET /partner/venues/{venueId}/resources. Do not invent this string."
          },
          "slot_start": {
            "type": "string",
            "format": "date-time"
          },
          "slot_duration_minutes": {
            "type": "integer",
            "minimum": 15,
            "maximum": 1440,
            "description": "Book the duration returned by /slots/availability rather than inventing a window."
          },
          "partner_id": {
            "type": "string",
            "description": "Ignored if sent. The partner is always the identity your x-api-key resolves to — this field cannot be used to act as a different partner. Omit it."
          },
          "idempotency_key": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Client-generated key for this logical hold. Retries with the same key return the original hold (201), including if the new body describes a different slot — hold reuse does not 409. UUID v4 recommended. Do not reuse a hold key across slots."
          },
          "customer_phone": {
            "type": "string",
            "description": "Optional. When present, membership discount may be applied at hold time so price_rupees matches what the customer will pay. Indian 10-digit mobile, optional +91."
          }
        },
        "example": {
          "venue_id": "a0000000-0000-4000-8000-000000000001",
          "resource_id": "badminton-court-1",
          "slot_start": "2026-09-15T18:00:00.000Z",
          "slot_duration_minutes": 60,
          "idempotency_key": "hold-9f2a-4c1e-8b7d-1a2b3c4d5e6f"
        }
      },
      "CreateHoldResponse": {
        "type": "object",
        "properties": {
          "hold_id": {
            "type": "string",
            "format": "uuid"
          },
          "slot_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "ACTIVE"
            ]
          },
          "hold_expiry_at": {
            "type": "string",
            "format": "date-time"
          },
          "price_rupees": {
            "type": "integer"
          }
        }
      },
      "ConfirmBookingRequest": {
        "type": "object",
        "required": [
          "hold_id",
          "payment_reference",
          "customer_name",
          "customer_phone",
          "idempotency_key"
        ],
        "properties": {
          "hold_id": {
            "type": "string",
            "format": "uuid"
          },
          "payment_reference": {
            "type": "string",
            "description": "Opaque string from your payment provider so you can correlate later. CBMS does not verify the payment on this call."
          },
          "customer_name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 100
          },
          "customer_phone": {
            "type": "string",
            "description": "Indian 10-digit mobile, optional +91."
          },
          "customer_email": {
            "type": "string",
            "format": "email"
          },
          "idempotency_key": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "use_package_credit": {
            "type": "boolean",
            "description": "If true, deduct one credit from the customer's active package instead of treating this as a paid confirm."
          }
        },
        "example": {
          "hold_id": "11111111-1111-4111-8111-111111111111",
          "payment_reference": "pay_example_ref",
          "customer_name": "Aarav Sharma",
          "customer_phone": "9876543210",
          "customer_email": "aarav@example.com",
          "idempotency_key": "confirm-9f2a-4c1e-8b7d-1a2b3c4d5e6f"
        }
      },
      "ConfirmBookingResponse": {
        "type": "object",
        "properties": {
          "booking_id": {
            "type": "string",
            "format": "uuid"
          },
          "slot_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "BOOKED"
            ]
          },
          "booked_at": {
            "type": "string",
            "format": "date-time"
          },
          "price_rupees": {
            "type": "integer"
          },
          "package_credit_consumed": {
            "type": "boolean",
            "description": "Present only when the request set use_package_credit. True only if a credit was actually consumed."
          }
        }
      },
      "BookingDetail": {
        "type": "object",
        "properties": {
          "booking_id": {
            "type": "string",
            "format": "uuid"
          },
          "hold_id": {
            "type": "string",
            "format": "uuid"
          },
          "slot_id": {
            "type": "string",
            "format": "uuid"
          },
          "venue_id": {
            "type": "string",
            "format": "uuid"
          },
          "partner_id": {
            "type": "string"
          },
          "resource_id": {
            "type": "string"
          },
          "slot_start": {
            "type": "string",
            "format": "date-time"
          },
          "slot_end": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string"
          },
          "booked_at": {
            "type": "string",
            "format": "date-time"
          },
          "price_rupees": {
            "type": "integer"
          },
          "payment_reference": {
            "type": "string"
          },
          "payment_method": {
            "type": "string",
            "nullable": true
          },
          "package_purchase_id": {
            "type": "string",
            "format": "uuid"
          },
          "customer_name": {
            "type": "string"
          },
          "customer_phone": {
            "type": "string"
          },
          "cancelled_at": {
            "type": "string",
            "format": "date-time"
          },
          "refunded_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "BookingListItem": {
        "type": "object",
        "properties": {
          "booking_id": {
            "type": "string",
            "format": "uuid"
          },
          "hold_id": {
            "type": "string",
            "format": "uuid"
          },
          "slot_id": {
            "type": "string",
            "format": "uuid"
          },
          "venue_id": {
            "type": "string",
            "format": "uuid"
          },
          "partner_id": {
            "type": "string"
          },
          "resource_id": {
            "type": "string"
          },
          "slot_start": {
            "type": "string",
            "format": "date-time"
          },
          "slot_end": {
            "type": "string",
            "format": "date-time"
          },
          "status": {
            "type": "string"
          },
          "booked_at": {
            "type": "string",
            "format": "date-time"
          },
          "price_rupees": {
            "type": "integer"
          },
          "customer_name": {
            "type": "string"
          },
          "customer_phone": {
            "type": "string"
          },
          "payment_method": {
            "type": "string",
            "nullable": true
          },
          "package_purchase_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "CancelOrRefundRequest": {
        "type": "object",
        "required": [
          "idempotency_key"
        ],
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 500
          },
          "idempotency_key": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          }
        }
      },
      "CancelHoldResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "example": "Hold released successfully"
          },
          "hold_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "CANCELLED"
            ]
          }
        }
      },
      "CancelBookingResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "example": "Booking cancelled successfully"
          }
        }
      },
      "RefundBookingResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "example": "Booking refunded successfully"
          }
        }
      },
      "WebhookSubscription": {
        "type": "object",
        "description": "A webhook subscription. secret_key is returned only on create and rotate (top-level field on those responses), not as a supported list field.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "partner_id": {
            "type": "string"
          },
          "event_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "booking_created",
                "booking_cancelled",
                "booking_refunded",
                "hold_created",
                "hold_cancelled",
                "hold_expired"
              ]
            }
          },
          "endpoint_url": {
            "type": "string",
            "format": "uri"
          },
          "is_active": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CreateWebhookRequest": {
        "type": "object",
        "required": [
          "endpoint_url",
          "event_types"
        ],
        "properties": {
          "endpoint_url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS (or HTTP in sandbox/local) URL that will receive POSTs."
          },
          "event_types": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string",
              "enum": [
                "booking_created",
                "booking_cancelled",
                "booking_refunded",
                "hold_created",
                "hold_cancelled",
                "hold_expired"
              ]
            }
          }
        },
        "example": {
          "endpoint_url": "https://partner.example.com/cbms/webhooks",
          "event_types": [
            "booking_created",
            "booking_cancelled",
            "hold_expired",
            "hold_cancelled"
          ]
        }
      },
      "CreateWebhookResponse": {
        "type": "object",
        "required": [
          "secret_key"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "secret_key": {
            "type": "string",
            "description": "HMAC key for X-CBMS-Signature. Returned here (and on rotate) — store it. Rotating issues a new secret."
          },
          "data": {
            "$ref": "#/components/schemas/WebhookSubscription"
          }
        }
      },
      "RotateWebhookResponse": {
        "type": "object",
        "required": [
          "secret_key"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "secret_key": {
            "type": "string",
            "description": "New HMAC key. The previous secret stops verifying new deliveries. Returned once for this rotation."
          },
          "data": {
            "$ref": "#/components/schemas/WebhookSubscription"
          }
        }
      },
      "WebhookDeliveryPayload": {
        "type": "object",
        "description": "JSON body POSTed to your endpoint. details varies by event_type — ignore unknown fields. event_id is stable across retries of the same state change; delivery_id identifies this attempt.",
        "properties": {
          "event_id": {
            "type": "string",
            "format": "uuid"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "booking_created",
              "booking_cancelled",
              "booking_refunded",
              "hold_created",
              "hold_cancelled",
              "hold_expired"
            ]
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "When the underlying booking event happened, not when this delivery attempt was sent."
          },
          "venue_id": {
            "type": "string",
            "format": "uuid"
          },
          "slot_id": {
            "type": "string"
          },
          "hold_id": {
            "type": "string",
            "nullable": true
          },
          "booking_id": {
            "type": "string",
            "nullable": true
          },
          "partner_id": {
            "type": "string",
            "description": "Originating partner of the state change, which may not be you."
          },
          "details": {
            "type": "object",
            "additionalProperties": true
          },
          "delivery_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "PartnerVenue": {
        "type": "object",
        "description": "A venue your API key is currently authorized to operate against.",
        "properties": {
          "venue_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "archived"
            ]
          }
        }
      },
      "PartnerResource": {
        "type": "object",
        "description": "A bookable resource at a venue you are authorized for. resource_id is exactly what /slots/availability and /bookings/hold expect.",
        "properties": {
          "resource_id": {
            "type": "string",
            "example": "badminton-court-1"
          },
          "venue_id": {
            "type": "string",
            "format": "uuid"
          },
          "resource_type": {
            "type": "string",
            "example": "badminton-court"
          },
          "sport_category": {
            "type": "string",
            "example": "racquet_sports"
          },
          "duration_minutes": {
            "type": "integer"
          },
          "price_rupees": {
            "type": "integer",
            "description": "Venue base price. /slots/availability is the source of truth for a given date (dynamic pricing, blackouts, existing holds)."
          },
          "operating_hours_start": {
            "type": "string",
            "example": "06:00"
          },
          "operating_hours_end": {
            "type": "string",
            "example": "22:00"
          },
          "closed_on": {
            "type": "string",
            "description": "Comma-separated closed weekdays, e.g. \"monday\". Absent if open every day."
          }
        }
      },
      "PackagePurchase": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "package_id": {
            "type": "string",
            "format": "uuid"
          },
          "customer_phone": {
            "type": "string"
          },
          "partner_id": {
            "type": "string"
          },
          "credits_remaining": {
            "type": "integer"
          },
          "payment_method": {
            "type": "string",
            "enum": [
              "cash",
              "upi",
              "card",
              "other"
            ]
          },
          "purchased_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WaitlistEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "venue_id": {
            "type": "string",
            "format": "uuid"
          },
          "resource_id": {
            "type": "string"
          },
          "slot_date": {
            "type": "string",
            "format": "date"
          },
          "slot_id": {
            "type": "string",
            "nullable": true
          },
          "customer_phone": {
            "type": "string"
          },
          "customer_name": {
            "type": "string",
            "nullable": true
          },
          "partner_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "waiting",
              "promoted",
              "expired",
              "cancelled"
            ]
          },
          "promoted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "JoinWaitlistRequest": {
        "type": "object",
        "required": [
          "venue_id",
          "resource_id",
          "slot_date",
          "customer_phone"
        ],
        "properties": {
          "venue_id": {
            "type": "string",
            "format": "uuid"
          },
          "resource_id": {
            "type": "string"
          },
          "slot_date": {
            "type": "string",
            "format": "date"
          },
          "customer_phone": {
            "type": "string"
          },
          "customer_name": {
            "type": "string"
          },
          "expires_in_days": {
            "type": "integer",
            "description": "Defaults to 7 if omitted."
          },
          "partner_id": {
            "type": "string",
            "description": "Ignored if sent. The partner is always the identity your x-api-key resolves to. Omit it."
          }
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Missing, invalid, revoked, or expired x-api-key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": "UNAUTHORIZED",
              "message": "API key is required"
            }
          }
        }
      },
      "VenueNotFound": {
        "description": "This venue id does not exist, or you are not currently authorized for it — the two cases are deliberately indistinguishable.",
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/Error"
                },
                {
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "VENUE_NOT_FOUND"
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "VenueNotAuthorized": {
        "description": "Your partner identity is not authorized for this venue. Distinct from ownership errors on the same hold/booking.",
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/Error"
                },
                {
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "VENUE_NOT_AUTHORIZED"
                      ]
                    }
                  }
                }
              ]
            }
          }
        }
      },
      "RateLimited": {
        "description": "Per-key rate limit exceeded. Default tier is 60 requests / 60 seconds. Honour Retry-After.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds to wait before retrying."
          },
          "X-RateLimit-Remaining": {
            "schema": {
              "type": "integer"
            }
          },
          "X-RateLimit-Reset-Ms": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/Error"
                },
                {
                  "properties": {
                    "error": {
                      "type": "string",
                      "enum": [
                        "RATE_LIMIT_EXCEEDED"
                      ]
                    },
                    "retry_after_seconds": {
                      "type": "integer"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  },
  "paths": {
    "/openapi.json": {
      "get": {
        "summary": "This OpenAPI document",
        "operationId": "getOpenApiSpec",
        "tags": [
          "Contract"
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI 3.0.3 document for the Partner API",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/slots/availability": {
      "get": {
        "summary": "Query available slots",
        "operationId": "getAvailability",
        "tags": [
          "Booking"
        ],
        "parameters": [
          {
            "name": "venue_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "date",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "YYYY-MM-DD"
          },
          {
            "name": "resource_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Slots for the date. is_available is a hint, not a reservation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "venue_id": {
                      "type": "string"
                    },
                    "date": {
                      "type": "string"
                    },
                    "slots": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AvailabilitySlot"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing or malformed query parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/VenueNotAuthorized"
          }
        }
      }
    },
    "/bookings/hold": {
      "post": {
        "summary": "Create a hold on a slot",
        "operationId": "createHold",
        "tags": [
          "Booking"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateHoldRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Hold created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateHoldResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error, past slot, or venue booking-rule rejection (SLOT_NOT_AVAILABLE)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/VenueNotAuthorized"
          },
          "409": {
            "description": "Slot not available (HELD/BOOKED or overlapping window) or TRANSFORMATION_CONFLICT",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/bookings/confirm": {
      "post": {
        "summary": "Confirm a booking from a hold",
        "operationId": "confirmBooking",
        "tags": [
          "Booking"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConfirmBookingRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Booking confirmed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConfirmBookingResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error or missing idempotency_key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Either the hold belongs to another partner (UNAUTHORIZED), or your partner lacks venue authorization (VENUE_NOT_AUTHORIZED, checked after ownership).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Hold not found (HOLD_NOT_FOUND)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "HOLD_EXPIRED, INVALID_HOLD_STATE, DOUBLE_BOOKING_ATTEMPT, or idempotency key mismatch",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/bookings": {
      "get": {
        "summary": "List bookings for the authenticated partner",
        "operationId": "listBookings",
        "tags": [
          "Booking"
        ],
        "parameters": [
          {
            "name": "venue_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Filter within your own bookings. Ignored as a way to see another partner's bookings."
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "customer_phone",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "customer_name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Partner-scoped bookings, newest booked_at first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "bookings": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/BookingListItem"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/bookings/{bookingId}": {
      "get": {
        "summary": "Get a booking by id",
        "operationId": "getBooking",
        "tags": [
          "Booking"
        ],
        "parameters": [
          {
            "name": "bookingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Booking you own. A missing id and another partner's booking both return 404.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookingDetail"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Booking not found (BOOKING_NOT_FOUND)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/partner/holds/{holdId}/cancel": {
      "post": {
        "summary": "Release an ACTIVE hold owned by the authenticated partner",
        "operationId": "cancelPartnerHold",
        "tags": [
          "Booking"
        ],
        "parameters": [
          {
            "name": "holdId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelOrRefundRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Hold released; reserved slots are AVAILABLE",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelHoldResponse"
                }
              }
            }
          },
          "400": {
            "description": "idempotency_key is required (IDEMPOTENCY_KEY_REQUIRED)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Either the hold belongs to another partner, or your partner lacks venue authorization (checked after ownership).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Hold not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Hold is not ACTIVE, or idempotency_key was already used for a different hold/operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/bookings/{bookingId}/cancel": {
      "post": {
        "summary": "Cancel a confirmed booking",
        "operationId": "cancelBooking",
        "tags": [
          "Booking"
        ],
        "parameters": [
          {
            "name": "bookingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelOrRefundRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Booking cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CancelBookingResponse"
                }
              }
            }
          },
          "400": {
            "description": "idempotency_key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Either the booking belongs to another partner, or your partner lacks venue authorization (checked after ownership).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Booking not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Booking cannot be cancelled (past slot or wrong state), or idempotency_key was already used for a different booking/operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/bookings/{bookingId}/refund": {
      "post": {
        "summary": "Refund a confirmed or already-cancelled booking",
        "description": "Marks the booking REFUNDED and frees the slot if it was still BOOKED. CBMS does not call a payment gateway to move money on this endpoint — reconciling the monetary refund is your responsibility.",
        "operationId": "refundBooking",
        "tags": [
          "Booking"
        ],
        "parameters": [
          {
            "name": "bookingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelOrRefundRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Booking refunded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RefundBookingResponse"
                }
              }
            }
          },
          "400": {
            "description": "idempotency_key is required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "Either the booking belongs to another partner, or your partner lacks venue authorization (checked after ownership).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Booking not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Already refunded, in a state that cannot be refunded, or idempotency_key was already used for a different booking/operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/packages/{packageId}/purchase": {
      "post": {
        "summary": "Purchase a package on behalf of a customer",
        "operationId": "purchasePackage",
        "tags": [
          "Packages"
        ],
        "parameters": [
          {
            "name": "packageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "customer_phone": {
                    "type": "string"
                  },
                  "payment_method": {
                    "type": "string",
                    "enum": [
                      "cash",
                      "upi",
                      "card",
                      "other"
                    ]
                  },
                  "idempotency_key": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  }
                },
                "required": [
                  "customer_phone",
                  "idempotency_key"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Package purchased (or, on replay of the same idempotency_key, the original purchase returned unchanged)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "purchase": {
                      "$ref": "#/components/schemas/PackagePurchase"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "idempotency_key is required, or the package is not active",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Package not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "idempotency_key was already used for a different package or customer",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/packages/purchases/{purchaseId}": {
      "get": {
        "summary": "Get a package purchase by id",
        "operationId": "getPackagePurchase",
        "tags": [
          "Packages"
        ],
        "parameters": [
          {
            "name": "purchaseId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The purchase, if it belongs to your partner",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "purchase": {
                      "$ref": "#/components/schemas/PackagePurchase"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Purchase not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/packages/active": {
      "get": {
        "summary": "List active package purchases for a customer at a venue",
        "operationId": "listActivePackagePurchases",
        "tags": [
          "Packages"
        ],
        "parameters": [
          {
            "name": "customer_phone",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "venue_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Active purchases",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "purchases": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PackagePurchase"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "customer_phone and venue_id are required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/waitlist": {
      "post": {
        "summary": "Join the waitlist for a sold-out slot",
        "description": "Naturally idempotent on (venue_id, resource_id, slot_date, customer_phone) — retrying the same join updates expires_at and resets status to waiting. No idempotency_key field.",
        "operationId": "joinWaitlist",
        "tags": [
          "Waitlist"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JoinWaitlistRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Waitlist entry created or re-activated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "entry": {
                      "$ref": "#/components/schemas/WaitlistEntry"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "get": {
        "summary": "List waitlist entries for a venue/resource/date",
        "description": "Scoped to your partner identity. Requires venue_id, resource_id, and slot_date.",
        "operationId": "listWaitlist",
        "tags": [
          "Waitlist"
        ],
        "parameters": [
          {
            "name": "venue_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "resource_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slot_date",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "waiting",
                "promoted",
                "expired",
                "cancelled"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching entries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "entries": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WaitlistEntry"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "venue_id, resource_id, and slot_date are required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/waitlist/{entryId}": {
      "delete": {
        "summary": "Cancel your waitlist entry",
        "operationId": "cancelWaitlistEntry",
        "tags": [
          "Waitlist"
        ],
        "parameters": [
          {
            "name": "entryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Cancelled"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Entry not found (or not yours)"
          }
        }
      }
    },
    "/partner/webhooks": {
      "get": {
        "summary": "List the authenticated partner's own webhook subscriptions",
        "description": "Scope is always the partner your API key resolves to — there is no partner_id parameter. Store secret_key from create/rotate; do not rely on list to retrieve it.",
        "operationId": "listWebhooks",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "Webhook subscriptions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "partner_id": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookSubscription"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "post": {
        "summary": "Create a webhook subscription for the authenticated partner",
        "description": "The subscription is always owned by the partner your API key resolves to — a partner_id field in the body is not read. secret_key is returned once on this response; store it. Signing: HMAC-SHA256 over `${X-CBMS-Timestamp}.${rawBody}`, header X-CBMS-Signature: sha256=<hex>. X-CBMS-Timestamp is the send time of this delivery attempt (retries get a fresh timestamp). Reject |now - timestamp| > 300s. Retries: 5 attempts, 10s POST timeout, backoff 5/15/30/60 minutes, then dead-letter. Event name for a confirmed booking is booking_created, not booking_confirmed.",
        "operationId": "createWebhook",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Subscription created. secret_key returned once — store it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateWebhookResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/partner/webhooks/{id}/rotate-secret": {
      "post": {
        "summary": "Rotate a webhook subscription's signing secret",
        "operationId": "rotateWebhookSecret",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "New secret_key returned once — store it, it cannot be retrieved again.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RotateWebhookResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Subscription not found (or not owned by your partner)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/partner/venues": {
      "get": {
        "summary": "List the venues your API key is currently authorized to operate against",
        "description": "Scope is always the partner your API key resolves to. No grants yet is a successful empty list, not an error.",
        "operationId": "listPartnerVenues",
        "tags": [
          "Venues"
        ],
        "responses": {
          "200": {
            "description": "Authorized venues",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PartnerVenue"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/partner/venues/{venueId}": {
      "get": {
        "summary": "Get a single venue you are authorized for",
        "operationId": "getPartnerVenue",
        "tags": [
          "Venues"
        ],
        "parameters": [
          {
            "name": "venueId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The venue",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "$ref": "#/components/schemas/PartnerVenue"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/VenueNotFound"
          }
        }
      }
    },
    "/partner/venues/{venueId}/resources": {
      "get": {
        "summary": "List the bookable resources at a venue you are authorized for",
        "description": "resource_id values are exactly what /slots/availability and /bookings/hold expect for this venue.",
        "operationId": "listPartnerVenueResources",
        "tags": [
          "Venues"
        ],
        "parameters": [
          {
            "name": "venueId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Resources at this venue",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PartnerResource"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/VenueNotFound"
          }
        }
      }
    },
    "/partner/observability": {
      "get": {
        "summary": "Aggregate stats for the authenticated partner's own webhook subscriptions and deliveries",
        "operationId": "getPartnerObservability",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "Subscription counts, per-event-type counts, per-status delivery counts, and the 10 most recent events",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "partner_id": {
                          "type": "string"
                        },
                        "webhook_subscriptions": {
                          "type": "object",
                          "properties": {
                            "total": {
                              "type": "integer"
                            },
                            "active": {
                              "type": "integer"
                            }
                          }
                        },
                        "event_counts": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "event_type": {
                                "type": "string"
                              },
                              "count": {
                                "type": "integer"
                              }
                            }
                          }
                        },
                        "delivery_status": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "status": {
                                "type": "string"
                              },
                              "count": {
                                "type": "integer"
                              }
                            }
                          }
                        },
                        "latest_events": {
                          "type": "array",
                          "items": {
                            "type": "object"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/partner/audit-events": {
      "get": {
        "summary": "Recent booking-domain events visible to the authenticated partner",
        "operationId": "getPartnerAuditEvents",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "venue_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "booking_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Matching events, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/partner/webhooks/{partnerId}/signature-sample": {
      "get": {
        "summary": "A worked signature test vector signed with your own webhook secret",
        "description": "Identity is the partner your API key resolves to. The partnerId path segment is required by the URL shape but is not used to select a different partner. Requires at least one webhook subscription so there is a secret to sign with.",
        "operationId": "getWebhookSignatureSample",
        "tags": [
          "Webhooks"
        ],
        "parameters": [
          {
            "name": "partnerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sample body, X-CBMS-Timestamp/X-CBMS-Signature headers, and the verification formula",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "algorithm": {
                          "type": "string",
                          "enum": [
                            "sha256"
                          ]
                        },
                        "headers": {
                          "type": "object",
                          "properties": {
                            "X-CBMS-Timestamp": {
                              "type": "string"
                            },
                            "X-CBMS-Signature": {
                              "type": "string"
                            }
                          }
                        },
                        "body": {
                          "type": "string"
                        },
                        "verify": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "No webhook subscriptions found for this partner"
          }
        }
      }
    }
  }
}
