{
  "openapi": "3.1.0",
  "info": {
    "title": "HolidayOS Connect API",
    "version": "1.0",
    "description": "Submit enquiries from your website or partner systems into HolidayOS, and receive customer-safe lifecycle events back over signed webhooks.",
    "contact": {
      "name": "HolidayOS",
      "url": "https://holidayos.ai/developers/connect",
      "email": "hello@holidayos.ai"
    }
  },
  "servers": [
    {
      "url": "https://api.new.holidayos.ai",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ConnectKey": [],
      "ConnectTenant": [],
      "ConnectSignature": []
    }
  ],
  "paths": {
    "/api/v1/crm/connect/events": {
      "post": {
        "tags": [
          "Connect"
        ],
        "summary": "Ingest a batch of Connect events",
        "description": "Accepts 1–100 event envelopes. Requires the `events:ingest` scope. Validation is all-or-nothing: a single bad envelope rejects the batch and writes nothing.",
        "operationId": "ingestConnectEvents",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "events"
                ],
                "properties": {
                  "events": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 100,
                    "items": {
                      "type": "object",
                      "required": [
                        "specVersion",
                        "eventId",
                        "eventType",
                        "occurredAt",
                        "tenant",
                        "origin",
                        "actor"
                      ],
                      "properties": {
                        "specVersion": {
                          "type": "string",
                          "maxLength": 16,
                          "example": "1.0"
                        },
                        "eventId": {
                          "type": "string",
                          "maxLength": 100,
                          "description": "Globally unique. The idempotency key — reuse it on retry."
                        },
                        "eventType": {
                          "type": "string",
                          "enum": [
                            "contact.identified",
                            "contact.updated",
                            "enquiry.submitted",
                            "traveller.discovery_upserted",
                            "trip.planning_started",
                            "trip.draft_updated",
                            "quote.requested",
                            "booking.started",
                            "booking.abandoned",
                            "booking.completed",
                            "booking.credit_applied",
                            "employee.credit_updated"
                          ]
                        },
                        "occurredAt": {
                          "type": "string",
                          "format": "date-time",
                          "description": "ISO-8601 instant the event occurred on the source system."
                        },
                        "tenant": {
                          "type": "string",
                          "maxLength": 100,
                          "description": "Must match the tenant bound to the API key.",
                          "example": "your-tenant-slug"
                        },
                        "origin": {
                          "type": "string",
                          "maxLength": 100,
                          "description": "Emitting system, used for loop prevention on the two-way channel."
                        },
                        "actor": {
                          "type": "object",
                          "required": [
                            "type"
                          ],
                          "description": "The traveller the event is about. At least one of email, phone, or externalId is required.",
                          "properties": {
                            "type": {
                              "type": "string",
                              "enum": [
                                "contact"
                              ]
                            },
                            "email": {
                              "type": "string",
                              "format": "email",
                              "maxLength": 320
                            },
                            "externalId": {
                              "type": "string",
                              "maxLength": 200
                            },
                            "name": {
                              "type": "string",
                              "maxLength": 200
                            },
                            "phone": {
                              "type": "string",
                              "maxLength": 40
                            }
                          },
                          "anyOf": [
                            {
                              "required": [
                                "email"
                              ]
                            },
                            {
                              "required": [
                                "phone"
                              ]
                            },
                            {
                              "required": [
                                "externalId"
                              ]
                            }
                          ]
                        },
                        "payload": {
                          "type": "object",
                          "additionalProperties": true,
                          "description": "Event-specific body. Intentionally open for the public spec."
                        }
                      }
                    }
                  }
                }
              },
              "example": {
                "events": [
                  {
                    "specVersion": "1.0",
                    "eventId": "source_event_id",
                    "eventType": "enquiry.submitted",
                    "occurredAt": "2026-08-23T09:15:00Z",
                    "tenant": "your-tenant-slug",
                    "origin": "source-system",
                    "actor": {
                      "type": "contact",
                      "email": "traveler@example.com",
                      "name": "Ana Silva",
                      "phone": "+60123456789"
                    },
                    "payload": {
                      "destination": "Bali",
                      "travelDates": {
                        "startDate": "2026-11-04",
                        "endDate": "2026-11-10"
                      },
                      "party": {
                        "adults": 3,
                        "children": 0,
                        "rooms": 1
                      },
                      "message": "Customer requested advisor pricing before checkout.",
                      "quote": {
                        "status": "pending",
                        "currency": "USD"
                      },
                      "attribution": {
                        "source": "google",
                        "medium": "cpc",
                        "campaign": "bali-nov",
                        "term": "bali holiday packages",
                        "landingPath": "/campaign"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Batch processed. Inspect `results` for the per-event outcome.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "accepted",
                    "duplicate",
                    "failed",
                    "results"
                  ],
                  "properties": {
                    "accepted": {
                      "type": "integer"
                    },
                    "duplicate": {
                      "type": "integer"
                    },
                    "failed": {
                      "type": "integer"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "eventId",
                          "status"
                        ],
                        "properties": {
                          "eventId": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "accepted",
                              "duplicate",
                              "failed"
                            ]
                          },
                          "error": {
                            "type": "string",
                            "description": "Present only on `failed`. A safe, non-leaking reason."
                          },
                          "clientId": {
                            "type": "string",
                            "description": "The client the event matched or created."
                          },
                          "leadId": {
                            "type": "string",
                            "description": "The enquiry the event opened or attached to, when it has one."
                          },
                          "tripId": {
                            "type": "string",
                            "description": "The enquiry's trip workspace, once one exists."
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "accepted": 1,
                  "duplicate": 0,
                  "failed": 0,
                  "results": [
                    {
                      "eventId": "source_event_id",
                      "status": "accepted",
                      "clientId": "6ab3d852869e40b4db978f8e",
                      "leadId": "6ab8e3597a5f4efc2b5258cc",
                      "tripId": "6ab8e3597a5f4efc2b5258ef"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The batch was rejected before anything was written. An envelope failed validation (missing field, unknown `eventType`, malformed `occurredAt`). `actor` carries none of `email`, `phone`, or `externalId` — there is no key to dedupe on. The envelope `tenant` does not match the authenticated key's tenant. An `eventId` starts with `connect-api:`, which the records API reserves for its own writes. More than 100 events, or an empty `events` array. Fix the payload. Retrying the same body will fail identically."
          },
          "401": {
            "description": "`Invalid Connect credentials` — one generic message for every auth failure. `X-Connect-Key`, `X-Connect-Signature`, or `X-Connect-Tenant` missing or malformed. The key prefix is unknown, revoked, or expired. The signature does not verify — usually because the signed bytes are not the bytes sent. The timestamp is outside the ±5 minute window (check server clock drift). The exact same signature was already used inside the freshness window (replay). Re-sign with a fresh timestamp. If it still fails, verify you sign the raw body bytes you actually transmit."
          },
          "403": {
            "description": "Authenticated, but not authorised. The key does not hold the route's scope — `events:ingest` for `/events`, or the one the Records API lists. `X-Connect-Tenant` does not match the tenant bound to the key. Fix the key's scopes or the tenant header. Retrying unchanged will fail."
          },
          "503": {
            "description": "Replay protection is temporarily unavailable. The replay guard store could not be reached. Safe to retry shortly with the same `eventId` values — nothing was ingested."
          }
        }
      }
    },
    "/api/v1/crm/connect/clients": {
      "post": {
        "tags": [
          "Connect records"
        ],
        "summary": "Create a client",
        "description": "Creates a client owned by your Connect identity. Needs at least one of `email`, `phone` or `externalId`. When that identity already exists the answer is `409 client_exists` with its `clientId` — read or patch that one instead. An address on a company domain your agency already has as a company account joins that account.\n\nRequires the `clients:write` scope and a `v2` signature.",
        "operationId": "createAClient",
        "security": [
          {
            "ConnectKey": [],
            "ConnectTenant": [],
            "ConnectSignatureV2": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Full name. A new client without one is named after its email."
                  },
                  "email": {
                    "type": "string",
                    "description": "The strongest identity: matched case-insensitively."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Used to match only when no email is sent."
                  },
                  "company": {
                    "type": "string",
                    "description": "The person's company, as a label."
                  },
                  "externalId": {
                    "type": "string",
                    "description": "Your own ID for this person. Matched when no email is sent."
                  },
                  "marketingOptIn": {
                    "type": "boolean",
                    "description": "Whether they agreed to marketing."
                  },
                  "travelers": {
                    "type": "array",
                    "description": "Array of `{ name, type?: adult|child|infant, age?, email?, phone? }`, at most 50. On a PATCH it replaces the client's traveller roster."
                  }
                }
              },
              "example": {
                "name": "Ana Silva",
                "email": "ana@example.com",
                "phone": "+60123456789",
                "externalId": "user_8841",
                "marketingOptIn": true,
                "travelers": [
                  {
                    "name": "Leo Silva",
                    "type": "child",
                    "age": 9
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Create a client",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ConnectClient"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "6ab3d852869e40b4db978f8e",
                    "name": "Ana Silva",
                    "email": "ana@example.com",
                    "phone": "+60123456789",
                    "company": null,
                    "externalId": "user_8841",
                    "marketingOptIn": true,
                    "clientType": "individual",
                    "travelers": [
                      {
                        "name": "Leo Silva",
                        "type": "child",
                        "age": 9,
                        "email": null,
                        "phone": null
                      }
                    ],
                    "createdAt": "2026-10-07T09:04:37.000Z",
                    "updatedAt": "2026-10-07T09:04:37.000Z"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "See `code` — the records error table lists every value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Connect records"
        ],
        "summary": "Look a client up",
        "description": "Exact identity lookup, with the same precedence as matching: `email`, else `externalId`, else `phone`. Returns an empty list or a list of one.\n\nRequires the `clients:read` scope and a `v2` signature.",
        "operationId": "lookAClientUp",
        "security": [
          {
            "ConnectKey": [],
            "ConnectTenant": [],
            "ConnectSignatureV2": []
          }
        ],
        "parameters": [
          {
            "name": "email",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Case-insensitive."
          },
          {
            "name": "phone",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Compared by digits."
          },
          {
            "name": "externalId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Your own ID for the person."
          }
        ],
        "responses": {
          "200": {
            "description": "Look a client up",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ConnectClient"
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "6ab3d852869e40b4db978f8e",
                      "name": "Ana Silva",
                      "email": "ana@example.com",
                      "phone": "+60123456789",
                      "company": null,
                      "externalId": "user_8841",
                      "marketingOptIn": true,
                      "clientType": "individual",
                      "travelers": [
                        {
                          "name": "Leo Silva",
                          "type": "child",
                          "age": 9,
                          "email": null,
                          "phone": null
                        }
                      ],
                      "createdAt": "2026-10-07T09:04:37.000Z",
                      "updatedAt": "2026-10-07T09:04:37.000Z"
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "See `code` — the records error table lists every value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crm/connect/clients/{clientId}": {
      "get": {
        "tags": [
          "Connect records"
        ],
        "summary": "Read a client",
        "description": "A client of another agency is a 404, never a 403.\n\nRequires the `clients:read` scope and a `v2` signature.",
        "operationId": "readAClient",
        "security": [
          {
            "ConnectKey": [],
            "ConnectTenant": [],
            "ConnectSignatureV2": []
          }
        ],
        "parameters": [
          {
            "name": "clientId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Read a client",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ConnectClient"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "6ab3d852869e40b4db978f8e",
                    "name": "Ana Silva",
                    "email": "ana@example.com",
                    "phone": "+60123456789",
                    "company": null,
                    "externalId": "user_8841",
                    "marketingOptIn": true,
                    "clientType": "individual",
                    "travelers": [
                      {
                        "name": "Leo Silva",
                        "type": "child",
                        "age": 9,
                        "email": null,
                        "phone": null
                      }
                    ],
                    "createdAt": "2026-10-07T09:04:37.000Z",
                    "updatedAt": "2026-10-07T09:04:37.000Z"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "See `code` — the records error table lists every value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Connect records"
        ],
        "summary": "Update a client",
        "description": "Changes only the fields you send; an omitted field is left as it is. Changing `email` or `externalId` to one another client holds is `409 identity_taken` with that client's ID.\n\nRequires the `clients:write` scope and a `v2` signature.",
        "operationId": "updateAClient",
        "security": [
          {
            "ConnectKey": [],
            "ConnectTenant": [],
            "ConnectSignatureV2": []
          }
        ],
        "parameters": [
          {
            "name": "clientId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "The record's ETag; a stale one is 412."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Full name. A new client without one is named after its email."
                  },
                  "email": {
                    "type": "string",
                    "description": "The strongest identity: matched case-insensitively."
                  },
                  "phone": {
                    "type": "string",
                    "description": "Used to match only when no email is sent."
                  },
                  "company": {
                    "type": "string",
                    "description": "The person's company, as a label."
                  },
                  "externalId": {
                    "type": "string",
                    "description": "Your own ID for this person. Matched when no email is sent."
                  },
                  "marketingOptIn": {
                    "type": "boolean",
                    "description": "Whether they agreed to marketing."
                  },
                  "travelers": {
                    "type": "array",
                    "description": "Array of `{ name, type?: adult|child|infant, age?, email?, phone? }`, at most 50. On a PATCH it replaces the client's traveller roster."
                  }
                }
              },
              "example": {
                "phone": "+447700900123",
                "marketingOptIn": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Update a client",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ConnectClient"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "6ab3d852869e40b4db978f8e",
                    "name": "Ana Silva",
                    "email": "ana@example.com",
                    "phone": "+60123456789",
                    "company": null,
                    "externalId": "user_8841",
                    "marketingOptIn": true,
                    "clientType": "individual",
                    "travelers": [
                      {
                        "name": "Leo Silva",
                        "type": "child",
                        "age": 9,
                        "email": null,
                        "phone": null
                      }
                    ],
                    "createdAt": "2026-10-07T09:04:37.000Z",
                    "updatedAt": "2026-10-07T09:04:37.000Z"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "See `code` — the records error table lists every value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crm/connect/leads": {
      "post": {
        "tags": [
          "Connect records"
        ],
        "summary": "Create an enquiry",
        "description": "Runs exactly the path an `enquiry.submitted` event takes: the client is matched or created, the enquiry opens at `inquiry` with an enquiry number, is routed to an advisor, gets a trip workspace, and `message` opens its inbox thread. Send `clientId` to attach it to a client you already have, or `contact` to match one. Returns the enquiry with `clientId` and `tripId`.\n\nRequires the `leads:write` scope and a `v2` signature.",
        "operationId": "createAnEnquiry",
        "security": [
          {
            "ConnectKey": [],
            "ConnectTenant": [],
            "ConnectSignatureV2": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "contact": {
                    "type": "object",
                    "description": "`{ name, email, phone, externalId }`. Needed unless you send `clientId`."
                  },
                  "clientId": {
                    "type": "string",
                    "description": "Attach to this client; it is never duplicated."
                  },
                  "externalId": {
                    "type": "string",
                    "description": "Your own ID for this enquiry, for `GET /leads?externalId=`."
                  },
                  "title": {
                    "type": "string",
                    "description": "The enquiry or trip title advisors see."
                  },
                  "destination": {
                    "type": "string",
                    "description": "Free text, e.g. `Bali`."
                  },
                  "travelDates": {
                    "type": "object",
                    "description": "`{ startDate, endDate }`, each `YYYY-MM-DD`."
                  },
                  "party": {
                    "type": "object",
                    "description": "`{ adults, children, childAges, rooms }`. Stored as the party count, never inferred from a traveller list."
                  },
                  "budget": {
                    "type": "object",
                    "description": "`{ amount, currency }` when you know the figure and currency, otherwise `{ notes }` with the customer's words. Replaces the stated budget as a whole."
                  },
                  "guestNationality": {
                    "type": "string",
                    "description": "ISO 3166-1 alpha-2 passport country of the party; `\"\"` clears it."
                  },
                  "itinerary": {
                    "type": "object",
                    "description": "A customized itinerary snapshot — the same object `enquiry.submitted` takes as `itinerarySnapshot`: `{ title, days: [{ title, items: [{ title, … }] }] }`."
                  },
                  "message": {
                    "type": "string",
                    "description": "The customer's own words. Opens the enquiry's inbox thread."
                  },
                  "attribution": {
                    "type": "object",
                    "description": "`{ source, medium, campaign, term, content, landingPath, referrer }` — the campaign that earned the enquiry."
                  }
                }
              },
              "example": {
                "clientId": "6ab3d852869e40b4db978f8e",
                "externalId": "enquiry_2207",
                "destination": "Bali",
                "travelDates": {
                  "startDate": "2026-11-04",
                  "endDate": "2026-11-10"
                },
                "party": {
                  "adults": 2,
                  "children": 1,
                  "childAges": [
                    7
                  ],
                  "rooms": 1
                },
                "budget": {
                  "notes": "around $3k per person"
                },
                "message": "Anniversary trip; we'd like quiet villas."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Create an enquiry",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ConnectLead"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "6ab8e3597a5f4efc2b5258cc",
                    "enquiryNumber": "HOS-2026-000412",
                    "title": "Ana Silva — Bali",
                    "stage": "inquiry",
                    "followUp": false,
                    "clientId": "6ab3d852869e40b4db978f8e",
                    "tripId": "6ab8e3597a5f4efc2b5258ef",
                    "externalId": "enquiry_2207",
                    "owner": {
                      "email": "meera@youragency.com",
                      "name": "Meera"
                    },
                    "destination": "Bali",
                    "travelDates": {
                      "startDate": "2026-11-04",
                      "endDate": "2026-11-10"
                    },
                    "party": {
                      "adults": 2,
                      "children": 1,
                      "childAges": [
                        7
                      ],
                      "rooms": 1
                    },
                    "budget": {
                      "amount": null,
                      "currency": null,
                      "notes": "around $3k per person"
                    },
                    "createdAt": "2026-10-07T09:05:12.000Z",
                    "updatedAt": "2026-10-07T09:05:13.000Z"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "See `code` — the records error table lists every value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectError"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Connect records"
        ],
        "summary": "Look an enquiry up by your ID",
        "description": "Finds the enquiry you created with that `externalId` (or sent as `payload.externalLeadId`), in your agency only.\n\nRequires the `leads:read` scope and a `v2` signature.",
        "operationId": "lookAnEnquiryUpByYourID",
        "security": [
          {
            "ConnectKey": [],
            "ConnectTenant": [],
            "ConnectSignatureV2": []
          }
        ],
        "parameters": [
          {
            "name": "externalId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Your own ID for the enquiry."
          }
        ],
        "responses": {
          "200": {
            "description": "Look an enquiry up by your ID",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ConnectLead"
                      }
                    }
                  }
                },
                "example": {
                  "data": [
                    {
                      "id": "6ab8e3597a5f4efc2b5258cc",
                      "enquiryNumber": "HOS-2026-000412",
                      "title": "Ana Silva — Bali",
                      "stage": "inquiry",
                      "followUp": false,
                      "clientId": "6ab3d852869e40b4db978f8e",
                      "tripId": "6ab8e3597a5f4efc2b5258ef",
                      "externalId": "enquiry_2207",
                      "owner": {
                        "email": "meera@youragency.com",
                        "name": "Meera"
                      },
                      "destination": "Bali",
                      "travelDates": {
                        "startDate": "2026-11-04",
                        "endDate": "2026-11-10"
                      },
                      "party": {
                        "adults": 2,
                        "children": 1,
                        "childAges": [
                          7
                        ],
                        "rooms": 1
                      },
                      "budget": {
                        "amount": null,
                        "currency": null,
                        "notes": "around $3k per person"
                      },
                      "createdAt": "2026-10-07T09:05:12.000Z",
                      "updatedAt": "2026-10-07T09:05:13.000Z"
                    }
                  ]
                }
              }
            }
          },
          "4XX": {
            "description": "See `code` — the records error table lists every value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crm/connect/leads/{leadId}": {
      "get": {
        "tags": [
          "Connect records"
        ],
        "summary": "Read an enquiry",
        "description": "The enquiry with its trip summary. Once a trip exists it owns the pipeline stage, so `stage` is the trip's — what the advisor's board shows.\n\nRequires the `leads:read` scope and a `v2` signature.",
        "operationId": "readAnEnquiry",
        "security": [
          {
            "ConnectKey": [],
            "ConnectTenant": [],
            "ConnectSignatureV2": []
          }
        ],
        "parameters": [
          {
            "name": "leadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Read an enquiry",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ConnectLead"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "6ab8e3597a5f4efc2b5258cc",
                    "enquiryNumber": "HOS-2026-000412",
                    "title": "Ana Silva — Bali",
                    "stage": "inquiry",
                    "followUp": false,
                    "clientId": "6ab3d852869e40b4db978f8e",
                    "tripId": "6ab8e3597a5f4efc2b5258ef",
                    "externalId": "enquiry_2207",
                    "owner": {
                      "email": "meera@youragency.com",
                      "name": "Meera"
                    },
                    "destination": "Bali",
                    "travelDates": {
                      "startDate": "2026-11-04",
                      "endDate": "2026-11-10"
                    },
                    "party": {
                      "adults": 2,
                      "children": 1,
                      "childAges": [
                        7
                      ],
                      "rooms": 1
                    },
                    "budget": {
                      "amount": null,
                      "currency": null,
                      "notes": "around $3k per person"
                    },
                    "createdAt": "2026-10-07T09:05:12.000Z",
                    "updatedAt": "2026-10-07T09:05:13.000Z"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "See `code` — the records error table lists every value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Connect records"
        ],
        "summary": "Update an enquiry",
        "description": "Enquiry-level changes. `stage` goes through the same rules an advisor meets: proposal, booking and travel stages are set by their own workflows (`422 stage_not_allowed`), and `lost` needs a `reason` of 5+ characters (`422 reason_required`). `owner` must be an active member of your agency (`422 owner_not_member`); the new owner is notified.\n\nRequires the `leads:write` scope and a `v2` signature.",
        "operationId": "updateAnEnquiry",
        "security": [
          {
            "ConnectKey": [],
            "ConnectTenant": [],
            "ConnectSignatureV2": []
          }
        ],
        "parameters": [
          {
            "name": "leadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "The record's ETag; a stale one is 412."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "stage": {
                    "type": "string",
                    "description": "`inquiry`, `follow_up`, `building_proposal`, `negotiation` or `lost`."
                  },
                  "reason": {
                    "type": "string",
                    "description": "Why the stage changed. Required for `lost`."
                  },
                  "owner": {
                    "type": "string",
                    "description": "An active member's email."
                  },
                  "followUp": {
                    "type": "boolean",
                    "description": "Flag the enquiry for follow-up."
                  },
                  "title": {
                    "type": "string",
                    "description": "The enquiry title."
                  }
                }
              },
              "example": {
                "stage": "lost",
                "reason": "Booked with another agency"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Update an enquiry",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ConnectLead"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "6ab8e3597a5f4efc2b5258cc",
                    "enquiryNumber": "HOS-2026-000412",
                    "title": "Ana Silva — Bali",
                    "stage": "inquiry",
                    "followUp": false,
                    "clientId": "6ab3d852869e40b4db978f8e",
                    "tripId": "6ab8e3597a5f4efc2b5258ef",
                    "externalId": "enquiry_2207",
                    "owner": {
                      "email": "meera@youragency.com",
                      "name": "Meera"
                    },
                    "destination": "Bali",
                    "travelDates": {
                      "startDate": "2026-11-04",
                      "endDate": "2026-11-10"
                    },
                    "party": {
                      "adults": 2,
                      "children": 1,
                      "childAges": [
                        7
                      ],
                      "rooms": 1
                    },
                    "budget": {
                      "amount": null,
                      "currency": null,
                      "notes": "around $3k per person"
                    },
                    "createdAt": "2026-10-07T09:05:12.000Z",
                    "updatedAt": "2026-10-07T09:05:13.000Z"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "See `code` — the records error table lists every value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectError"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/crm/connect/leads/{leadId}/trip": {
      "get": {
        "tags": [
          "Connect records"
        ],
        "summary": "Read an enquiry's trip",
        "description": "The trip workspace: brief, stage, owner and whether a proposal has been sent. `409 trip_not_open` when the enquiry has no trip yet.\n\nRequires the `leads:read` scope and a `v2` signature.",
        "operationId": "readAnEnquirysTrip",
        "security": [
          {
            "ConnectKey": [],
            "ConnectTenant": [],
            "ConnectSignatureV2": []
          }
        ],
        "parameters": [
          {
            "name": "leadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Read an enquiry's trip",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ConnectTrip"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "6ab8e3597a5f4efc2b5258ef",
                    "leadId": "6ab8e3597a5f4efc2b5258cc",
                    "enquiryNumber": "HOS-2026-000412",
                    "title": "Ana Silva — Bali",
                    "stage": "inquiry",
                    "destination": "Bali",
                    "travelDates": {
                      "startDate": "2026-12-01",
                      "endDate": "2026-12-07"
                    },
                    "party": {
                      "adults": 3,
                      "children": 1,
                      "childAges": [
                        7
                      ],
                      "rooms": 1
                    },
                    "budget": {
                      "amount": null,
                      "currency": null,
                      "notes": "around $3k per person"
                    },
                    "guestNationality": null,
                    "owner": {
                      "email": "meera@youragency.com",
                      "name": "Meera"
                    },
                    "proposal": {
                      "status": "draft",
                      "sentAt": null
                    },
                    "createdAt": "2026-10-07T09:05:13.000Z",
                    "updatedAt": "2026-10-08T14:20:00.000Z"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "See `code` — the records error table lists every value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectError"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Connect records"
        ],
        "summary": "Post a customer's changes to their trip",
        "description": "Use this when the customer changes their trip on your side. Brief fields update the trip workspace; a date change is recorded as a correction with `changeSummary` as its reason. A new `itinerary` replaces the draft proposal only while the enquiry is at `inquiry`/`follow_up` and nothing has been sent — otherwise (or if the update itself fails) the response says `itineraryApplied: false` with `itineraryNotAppliedReason` (`advisor_working`, `proposal_sent`, `no_proposal` or `update_failed`) and the advisor decides. Either way, what changed (before → after), `changeSummary` and the customer's `message` are posted to the enquiry's inbox thread and its owner is notified. A closed enquiry (lost, archived, booked or travelled) answers `409 trip_closed`: send the change as a new enquiry instead.\n\nRequires the `leads:write` scope and a `v2` signature.",
        "operationId": "postACustomersChangesToTheirTrip",
        "security": [
          {
            "ConnectKey": [],
            "ConnectTenant": [],
            "ConnectSignatureV2": []
          }
        ],
        "parameters": [
          {
            "name": "leadId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "The record's ETag; a stale one is 412."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "The enquiry or trip title advisors see."
                  },
                  "destination": {
                    "type": "string",
                    "description": "Free text, e.g. `Bali`."
                  },
                  "travelDates": {
                    "type": "object",
                    "description": "`{ startDate, endDate }`, each `YYYY-MM-DD`."
                  },
                  "party": {
                    "type": "object",
                    "description": "`{ adults, children, childAges, rooms }`. Stored as the party count, never inferred from a traveller list."
                  },
                  "budget": {
                    "type": "object",
                    "description": "`{ amount, currency }` when you know the figure and currency, otherwise `{ notes }` with the customer's words. Replaces the stated budget as a whole."
                  },
                  "guestNationality": {
                    "type": "string",
                    "description": "ISO 3166-1 alpha-2 passport country of the party; `\"\"` clears it."
                  },
                  "itinerary": {
                    "type": "object",
                    "description": "A customized itinerary snapshot — the same object `enquiry.submitted` takes as `itinerarySnapshot`: `{ title, days: [{ title, items: [{ title, … }] }] }`."
                  },
                  "message": {
                    "type": "string",
                    "description": "The customer's own words, posted to the inbox thread."
                  },
                  "changeSummary": {
                    "type": "string",
                    "description": "One line on what changed; also the reason recorded on a date change."
                  }
                }
              },
              "example": {
                "travelDates": {
                  "startDate": "2026-12-01",
                  "endDate": "2026-12-07"
                },
                "party": {
                  "adults": 3
                },
                "changeSummary": "Customer moved the trip to December and added a traveller",
                "message": "My sister is joining us!"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Post a customer's changes to their trip",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ConnectTrip"
                    }
                  }
                },
                "example": {
                  "data": {
                    "id": "6ab8e3597a5f4efc2b5258ef",
                    "leadId": "6ab8e3597a5f4efc2b5258cc",
                    "enquiryNumber": "HOS-2026-000412",
                    "title": "Ana Silva — Bali",
                    "stage": "inquiry",
                    "destination": "Bali",
                    "travelDates": {
                      "startDate": "2026-12-01",
                      "endDate": "2026-12-07"
                    },
                    "party": {
                      "adults": 3,
                      "children": 1,
                      "childAges": [
                        7
                      ],
                      "rooms": 1
                    },
                    "budget": {
                      "amount": null,
                      "currency": null,
                      "notes": "around $3k per person"
                    },
                    "guestNationality": null,
                    "owner": {
                      "email": "meera@youragency.com",
                      "name": "Meera"
                    },
                    "proposal": {
                      "status": "draft",
                      "sentAt": null
                    },
                    "createdAt": "2026-10-07T09:05:13.000Z",
                    "updatedAt": "2026-10-08T14:20:00.000Z"
                  }
                }
              }
            }
          },
          "4XX": {
            "description": "See `code` — the records error table lists every value.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConnectError"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "lead.assigned": {
      "post": {
        "summary": "An advisor was assigned, or reassigned, to an enquiry.",
        "operationId": "webhook_lead_assigned",
        "parameters": [
          {
            "name": "X-Connect-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "t=1787654321,v1=<hex>"
            },
            "description": "HMAC-SHA256 of `<t>.<raw body>` keyed by the subscription secret."
          },
          {
            "name": "X-Connect-Tenant",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "your-tenant-slug"
            }
          },
          {
            "name": "X-Connect-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "lead.assigned"
            }
          },
          {
            "name": "X-Connect-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Delivery row id. Stable across retries of the same delivery."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "specVersion",
                  "eventId",
                  "eventType",
                  "occurredAt",
                  "tenant",
                  "origin",
                  "actor",
                  "payload"
                ],
                "properties": {
                  "specVersion": {
                    "type": "string",
                    "example": "1.0"
                  },
                  "eventId": {
                    "type": "string",
                    "description": "UUID. Stable across retries — dedupe on it."
                  },
                  "eventType": {
                    "type": "string",
                    "enum": [
                      "lead.assigned",
                      "lead.stage_changed",
                      "proposal.sent",
                      "proposal.ready",
                      "proposal.viewed",
                      "message.posted",
                      "booking.confirmed",
                      "booking.cancelled"
                    ]
                  },
                  "occurredAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "tenant": {
                    "type": "string",
                    "example": "your-tenant-slug"
                  },
                  "origin": {
                    "type": "string",
                    "example": "crm"
                  },
                  "actor": {
                    "type": "object",
                    "required": [
                      "type"
                    ],
                    "description": "The traveller the event is about. At least one of email, phone, or externalId is required.",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "contact"
                        ]
                      },
                      "email": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 320
                      },
                      "externalId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "phone": {
                        "type": "string",
                        "maxLength": 40
                      }
                    },
                    "anyOf": [
                      {
                        "required": [
                          "email"
                        ]
                      },
                      {
                        "required": [
                          "phone"
                        ]
                      },
                      {
                        "required": [
                          "externalId"
                        ]
                      }
                    ]
                  },
                  "payload": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "specVersion": "1.0",
                "eventId": "5f1c0000-0000-4000-8000-000000000000",
                "eventType": "lead.assigned",
                "occurredAt": "2026-08-23T09:15:00Z",
                "tenant": "your-tenant-slug",
                "origin": "crm",
                "actor": {
                  "type": "contact",
                  "email": "traveler@example.com",
                  "name": "Ana Silva"
                },
                "payload": {
                  "leadId": "lead_01H…",
                  "owner": "advisor@agency.com",
                  "title": "Ana Silva — Bali"
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Return within 10s or the delivery is retried."
          }
        }
      }
    },
    "lead.stage_changed": {
      "post": {
        "summary": "An enquiry moved between pipeline stages.",
        "operationId": "webhook_lead_stage_changed",
        "parameters": [
          {
            "name": "X-Connect-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "t=1787654321,v1=<hex>"
            },
            "description": "HMAC-SHA256 of `<t>.<raw body>` keyed by the subscription secret."
          },
          {
            "name": "X-Connect-Tenant",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "your-tenant-slug"
            }
          },
          {
            "name": "X-Connect-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "lead.stage_changed"
            }
          },
          {
            "name": "X-Connect-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Delivery row id. Stable across retries of the same delivery."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "specVersion",
                  "eventId",
                  "eventType",
                  "occurredAt",
                  "tenant",
                  "origin",
                  "actor",
                  "payload"
                ],
                "properties": {
                  "specVersion": {
                    "type": "string",
                    "example": "1.0"
                  },
                  "eventId": {
                    "type": "string",
                    "description": "UUID. Stable across retries — dedupe on it."
                  },
                  "eventType": {
                    "type": "string",
                    "enum": [
                      "lead.assigned",
                      "lead.stage_changed",
                      "proposal.sent",
                      "proposal.ready",
                      "proposal.viewed",
                      "message.posted",
                      "booking.confirmed",
                      "booking.cancelled"
                    ]
                  },
                  "occurredAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "tenant": {
                    "type": "string",
                    "example": "your-tenant-slug"
                  },
                  "origin": {
                    "type": "string",
                    "example": "crm"
                  },
                  "actor": {
                    "type": "object",
                    "required": [
                      "type"
                    ],
                    "description": "The traveller the event is about. At least one of email, phone, or externalId is required.",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "contact"
                        ]
                      },
                      "email": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 320
                      },
                      "externalId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "phone": {
                        "type": "string",
                        "maxLength": 40
                      }
                    },
                    "anyOf": [
                      {
                        "required": [
                          "email"
                        ]
                      },
                      {
                        "required": [
                          "phone"
                        ]
                      },
                      {
                        "required": [
                          "externalId"
                        ]
                      }
                    ]
                  },
                  "payload": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "specVersion": "1.0",
                "eventId": "5f1c0000-0000-4000-8000-000000000000",
                "eventType": "lead.stage_changed",
                "occurredAt": "2026-08-23T09:15:00Z",
                "tenant": "your-tenant-slug",
                "origin": "crm",
                "actor": {
                  "type": "contact",
                  "email": "traveler@example.com",
                  "name": "Ana Silva"
                },
                "payload": {
                  "leadId": "lead_01H…",
                  "fromStage": "inquiry",
                  "toStage": "proposal_sent",
                  "title": "Ana Silva — Bali"
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Return within 10s or the delivery is retried."
          }
        }
      }
    },
    "proposal.sent": {
      "post": {
        "summary": "A proposal was sent to the traveller. Carries the hosted proposal link.",
        "operationId": "webhook_proposal_sent",
        "parameters": [
          {
            "name": "X-Connect-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "t=1787654321,v1=<hex>"
            },
            "description": "HMAC-SHA256 of `<t>.<raw body>` keyed by the subscription secret."
          },
          {
            "name": "X-Connect-Tenant",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "your-tenant-slug"
            }
          },
          {
            "name": "X-Connect-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "proposal.sent"
            }
          },
          {
            "name": "X-Connect-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Delivery row id. Stable across retries of the same delivery."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "specVersion",
                  "eventId",
                  "eventType",
                  "occurredAt",
                  "tenant",
                  "origin",
                  "actor",
                  "payload"
                ],
                "properties": {
                  "specVersion": {
                    "type": "string",
                    "example": "1.0"
                  },
                  "eventId": {
                    "type": "string",
                    "description": "UUID. Stable across retries — dedupe on it."
                  },
                  "eventType": {
                    "type": "string",
                    "enum": [
                      "lead.assigned",
                      "lead.stage_changed",
                      "proposal.sent",
                      "proposal.ready",
                      "proposal.viewed",
                      "message.posted",
                      "booking.confirmed",
                      "booking.cancelled"
                    ]
                  },
                  "occurredAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "tenant": {
                    "type": "string",
                    "example": "your-tenant-slug"
                  },
                  "origin": {
                    "type": "string",
                    "example": "crm"
                  },
                  "actor": {
                    "type": "object",
                    "required": [
                      "type"
                    ],
                    "description": "The traveller the event is about. At least one of email, phone, or externalId is required.",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "contact"
                        ]
                      },
                      "email": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 320
                      },
                      "externalId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "phone": {
                        "type": "string",
                        "maxLength": 40
                      }
                    },
                    "anyOf": [
                      {
                        "required": [
                          "email"
                        ]
                      },
                      {
                        "required": [
                          "phone"
                        ]
                      },
                      {
                        "required": [
                          "externalId"
                        ]
                      }
                    ]
                  },
                  "payload": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "specVersion": "1.0",
                "eventId": "5f1c0000-0000-4000-8000-000000000000",
                "eventType": "proposal.sent",
                "occurredAt": "2026-08-23T09:15:00Z",
                "tenant": "your-tenant-slug",
                "origin": "crm",
                "actor": {
                  "type": "contact",
                  "email": "traveler@example.com",
                  "name": "Ana Silva"
                },
                "payload": {
                  "proposalId": "prop_01H…",
                  "tripId": "trip_01H…",
                  "title": "Bali — 6 nights",
                  "proposalUrl": "https://app.holidayos.ai/p/…",
                  "channel": "email"
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Return within 10s or the delivery is retried."
          }
        }
      }
    },
    "proposal.ready": {
      "post": {
        "summary": "Reserved in the allowlist. No code path emits it yet — do not wait on it.",
        "description": "Reserved in the allowlist; no code path emits this event yet.",
        "operationId": "webhook_proposal_ready",
        "parameters": [
          {
            "name": "X-Connect-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "t=1787654321,v1=<hex>"
            },
            "description": "HMAC-SHA256 of `<t>.<raw body>` keyed by the subscription secret."
          },
          {
            "name": "X-Connect-Tenant",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "your-tenant-slug"
            }
          },
          {
            "name": "X-Connect-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "proposal.ready"
            }
          },
          {
            "name": "X-Connect-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Delivery row id. Stable across retries of the same delivery."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "specVersion",
                  "eventId",
                  "eventType",
                  "occurredAt",
                  "tenant",
                  "origin",
                  "actor",
                  "payload"
                ],
                "properties": {
                  "specVersion": {
                    "type": "string",
                    "example": "1.0"
                  },
                  "eventId": {
                    "type": "string",
                    "description": "UUID. Stable across retries — dedupe on it."
                  },
                  "eventType": {
                    "type": "string",
                    "enum": [
                      "lead.assigned",
                      "lead.stage_changed",
                      "proposal.sent",
                      "proposal.ready",
                      "proposal.viewed",
                      "message.posted",
                      "booking.confirmed",
                      "booking.cancelled"
                    ]
                  },
                  "occurredAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "tenant": {
                    "type": "string",
                    "example": "your-tenant-slug"
                  },
                  "origin": {
                    "type": "string",
                    "example": "crm"
                  },
                  "actor": {
                    "type": "object",
                    "required": [
                      "type"
                    ],
                    "description": "The traveller the event is about. At least one of email, phone, or externalId is required.",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "contact"
                        ]
                      },
                      "email": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 320
                      },
                      "externalId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "phone": {
                        "type": "string",
                        "maxLength": 40
                      }
                    },
                    "anyOf": [
                      {
                        "required": [
                          "email"
                        ]
                      },
                      {
                        "required": [
                          "phone"
                        ]
                      },
                      {
                        "required": [
                          "externalId"
                        ]
                      }
                    ]
                  },
                  "payload": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "specVersion": "1.0",
                "eventId": "5f1c0000-0000-4000-8000-000000000000",
                "eventType": "proposal.ready",
                "occurredAt": "2026-08-23T09:15:00Z",
                "tenant": "your-tenant-slug",
                "origin": "crm",
                "actor": {
                  "type": "contact",
                  "email": "traveler@example.com",
                  "name": "Ana Silva"
                },
                "payload": {
                  "proposalId": "prop_01H…",
                  "tripId": "trip_01H…"
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Return within 10s or the delivery is retried."
          }
        }
      }
    },
    "proposal.viewed": {
      "post": {
        "summary": "The traveller opened the hosted proposal.",
        "operationId": "webhook_proposal_viewed",
        "parameters": [
          {
            "name": "X-Connect-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "t=1787654321,v1=<hex>"
            },
            "description": "HMAC-SHA256 of `<t>.<raw body>` keyed by the subscription secret."
          },
          {
            "name": "X-Connect-Tenant",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "your-tenant-slug"
            }
          },
          {
            "name": "X-Connect-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "proposal.viewed"
            }
          },
          {
            "name": "X-Connect-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Delivery row id. Stable across retries of the same delivery."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "specVersion",
                  "eventId",
                  "eventType",
                  "occurredAt",
                  "tenant",
                  "origin",
                  "actor",
                  "payload"
                ],
                "properties": {
                  "specVersion": {
                    "type": "string",
                    "example": "1.0"
                  },
                  "eventId": {
                    "type": "string",
                    "description": "UUID. Stable across retries — dedupe on it."
                  },
                  "eventType": {
                    "type": "string",
                    "enum": [
                      "lead.assigned",
                      "lead.stage_changed",
                      "proposal.sent",
                      "proposal.ready",
                      "proposal.viewed",
                      "message.posted",
                      "booking.confirmed",
                      "booking.cancelled"
                    ]
                  },
                  "occurredAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "tenant": {
                    "type": "string",
                    "example": "your-tenant-slug"
                  },
                  "origin": {
                    "type": "string",
                    "example": "crm"
                  },
                  "actor": {
                    "type": "object",
                    "required": [
                      "type"
                    ],
                    "description": "The traveller the event is about. At least one of email, phone, or externalId is required.",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "contact"
                        ]
                      },
                      "email": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 320
                      },
                      "externalId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "phone": {
                        "type": "string",
                        "maxLength": 40
                      }
                    },
                    "anyOf": [
                      {
                        "required": [
                          "email"
                        ]
                      },
                      {
                        "required": [
                          "phone"
                        ]
                      },
                      {
                        "required": [
                          "externalId"
                        ]
                      }
                    ]
                  },
                  "payload": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "specVersion": "1.0",
                "eventId": "5f1c0000-0000-4000-8000-000000000000",
                "eventType": "proposal.viewed",
                "occurredAt": "2026-08-23T09:15:00Z",
                "tenant": "your-tenant-slug",
                "origin": "crm",
                "actor": {
                  "type": "contact",
                  "email": "traveler@example.com",
                  "name": "Ana Silva"
                },
                "payload": {
                  "proposalId": "prop_01H…",
                  "tripId": "trip_01H…",
                  "title": "Bali — 6 nights",
                  "firstView": true,
                  "viewCount": 1
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Return within 10s or the delivery is retried."
          }
        }
      }
    },
    "message.posted": {
      "post": {
        "summary": "Reserved in the allowlist. No code path emits it yet — do not wait on it.",
        "description": "Reserved in the allowlist; no code path emits this event yet.",
        "operationId": "webhook_message_posted",
        "parameters": [
          {
            "name": "X-Connect-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "t=1787654321,v1=<hex>"
            },
            "description": "HMAC-SHA256 of `<t>.<raw body>` keyed by the subscription secret."
          },
          {
            "name": "X-Connect-Tenant",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "your-tenant-slug"
            }
          },
          {
            "name": "X-Connect-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "message.posted"
            }
          },
          {
            "name": "X-Connect-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Delivery row id. Stable across retries of the same delivery."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "specVersion",
                  "eventId",
                  "eventType",
                  "occurredAt",
                  "tenant",
                  "origin",
                  "actor",
                  "payload"
                ],
                "properties": {
                  "specVersion": {
                    "type": "string",
                    "example": "1.0"
                  },
                  "eventId": {
                    "type": "string",
                    "description": "UUID. Stable across retries — dedupe on it."
                  },
                  "eventType": {
                    "type": "string",
                    "enum": [
                      "lead.assigned",
                      "lead.stage_changed",
                      "proposal.sent",
                      "proposal.ready",
                      "proposal.viewed",
                      "message.posted",
                      "booking.confirmed",
                      "booking.cancelled"
                    ]
                  },
                  "occurredAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "tenant": {
                    "type": "string",
                    "example": "your-tenant-slug"
                  },
                  "origin": {
                    "type": "string",
                    "example": "crm"
                  },
                  "actor": {
                    "type": "object",
                    "required": [
                      "type"
                    ],
                    "description": "The traveller the event is about. At least one of email, phone, or externalId is required.",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "contact"
                        ]
                      },
                      "email": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 320
                      },
                      "externalId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "phone": {
                        "type": "string",
                        "maxLength": 40
                      }
                    },
                    "anyOf": [
                      {
                        "required": [
                          "email"
                        ]
                      },
                      {
                        "required": [
                          "phone"
                        ]
                      },
                      {
                        "required": [
                          "externalId"
                        ]
                      }
                    ]
                  },
                  "payload": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "specVersion": "1.0",
                "eventId": "5f1c0000-0000-4000-8000-000000000000",
                "eventType": "message.posted",
                "occurredAt": "2026-08-23T09:15:00Z",
                "tenant": "your-tenant-slug",
                "origin": "crm",
                "actor": {
                  "type": "contact",
                  "email": "traveler@example.com",
                  "name": "Ana Silva"
                },
                "payload": {
                  "messageId": "msg_01H…",
                  "tripId": "trip_01H…"
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Return within 10s or the delivery is retried."
          }
        }
      }
    },
    "booking.confirmed": {
      "post": {
        "summary": "The trip is booked. Carries the booking amount and, for a corporate employee, the travel credit the booking used. `bookingRef` identifies this booking; dedupe on it.",
        "operationId": "webhook_booking_confirmed",
        "parameters": [
          {
            "name": "X-Connect-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "t=1787654321,v1=<hex>"
            },
            "description": "HMAC-SHA256 of `<t>.<raw body>` keyed by the subscription secret."
          },
          {
            "name": "X-Connect-Tenant",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "your-tenant-slug"
            }
          },
          {
            "name": "X-Connect-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "booking.confirmed"
            }
          },
          {
            "name": "X-Connect-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Delivery row id. Stable across retries of the same delivery."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "specVersion",
                  "eventId",
                  "eventType",
                  "occurredAt",
                  "tenant",
                  "origin",
                  "actor",
                  "payload"
                ],
                "properties": {
                  "specVersion": {
                    "type": "string",
                    "example": "1.0"
                  },
                  "eventId": {
                    "type": "string",
                    "description": "UUID. Stable across retries — dedupe on it."
                  },
                  "eventType": {
                    "type": "string",
                    "enum": [
                      "lead.assigned",
                      "lead.stage_changed",
                      "proposal.sent",
                      "proposal.ready",
                      "proposal.viewed",
                      "message.posted",
                      "booking.confirmed",
                      "booking.cancelled"
                    ]
                  },
                  "occurredAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "tenant": {
                    "type": "string",
                    "example": "your-tenant-slug"
                  },
                  "origin": {
                    "type": "string",
                    "example": "crm"
                  },
                  "actor": {
                    "type": "object",
                    "required": [
                      "type"
                    ],
                    "description": "The traveller the event is about. At least one of email, phone, or externalId is required.",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "contact"
                        ]
                      },
                      "email": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 320
                      },
                      "externalId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "phone": {
                        "type": "string",
                        "maxLength": 40
                      }
                    },
                    "anyOf": [
                      {
                        "required": [
                          "email"
                        ]
                      },
                      {
                        "required": [
                          "phone"
                        ]
                      },
                      {
                        "required": [
                          "externalId"
                        ]
                      }
                    ]
                  },
                  "payload": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "specVersion": "1.0",
                "eventId": "5f1c0000-0000-4000-8000-000000000000",
                "eventType": "booking.confirmed",
                "occurredAt": "2026-08-23T09:15:00Z",
                "tenant": "your-tenant-slug",
                "origin": "crm",
                "actor": {
                  "type": "contact",
                  "email": "traveler@example.com",
                  "name": "Ana Silva"
                },
                "payload": {
                  "leadId": "lead_01H…",
                  "tripId": "trip_01H…",
                  "bookingRef": "trip_01H…:2026-10-06T09:00:00.000Z",
                  "enquiryNumber": "ENQ-2026-0142",
                  "amount": 71998,
                  "currency": "INR",
                  "paymentStatus": "paid",
                  "corporateCredit": {
                    "membershipId": "mem_…",
                    "creditUsedRupees": 2000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Return within 10s or the delivery is retried."
          }
        }
      }
    },
    "booking.cancelled": {
      "post": {
        "summary": "Sent by the Cancel booking action, with the same `bookingRef` as the booking.confirmed it cancels. Return any credit that booking used.",
        "operationId": "webhook_booking_cancelled",
        "parameters": [
          {
            "name": "X-Connect-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "t=1787654321,v1=<hex>"
            },
            "description": "HMAC-SHA256 of `<t>.<raw body>` keyed by the subscription secret."
          },
          {
            "name": "X-Connect-Tenant",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "your-tenant-slug"
            }
          },
          {
            "name": "X-Connect-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "example": "booking.cancelled"
            }
          },
          {
            "name": "X-Connect-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Delivery row id. Stable across retries of the same delivery."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "specVersion",
                  "eventId",
                  "eventType",
                  "occurredAt",
                  "tenant",
                  "origin",
                  "actor",
                  "payload"
                ],
                "properties": {
                  "specVersion": {
                    "type": "string",
                    "example": "1.0"
                  },
                  "eventId": {
                    "type": "string",
                    "description": "UUID. Stable across retries — dedupe on it."
                  },
                  "eventType": {
                    "type": "string",
                    "enum": [
                      "lead.assigned",
                      "lead.stage_changed",
                      "proposal.sent",
                      "proposal.ready",
                      "proposal.viewed",
                      "message.posted",
                      "booking.confirmed",
                      "booking.cancelled"
                    ]
                  },
                  "occurredAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "tenant": {
                    "type": "string",
                    "example": "your-tenant-slug"
                  },
                  "origin": {
                    "type": "string",
                    "example": "crm"
                  },
                  "actor": {
                    "type": "object",
                    "required": [
                      "type"
                    ],
                    "description": "The traveller the event is about. At least one of email, phone, or externalId is required.",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "contact"
                        ]
                      },
                      "email": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 320
                      },
                      "externalId": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "name": {
                        "type": "string",
                        "maxLength": 200
                      },
                      "phone": {
                        "type": "string",
                        "maxLength": 40
                      }
                    },
                    "anyOf": [
                      {
                        "required": [
                          "email"
                        ]
                      },
                      {
                        "required": [
                          "phone"
                        ]
                      },
                      {
                        "required": [
                          "externalId"
                        ]
                      }
                    ]
                  },
                  "payload": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              },
              "example": {
                "specVersion": "1.0",
                "eventId": "5f1c0000-0000-4000-8000-000000000000",
                "eventType": "booking.cancelled",
                "occurredAt": "2026-08-23T09:15:00Z",
                "tenant": "your-tenant-slug",
                "origin": "crm",
                "actor": {
                  "type": "contact",
                  "email": "traveler@example.com",
                  "name": "Ana Silva"
                },
                "payload": {
                  "leadId": "lead_01H…",
                  "tripId": "trip_01H…",
                  "bookingRef": "trip_01H…:2026-10-06T09:00:00.000Z",
                  "enquiryNumber": "ENQ-2026-0142"
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Acknowledged. Return within 10s or the delivery is retried."
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ConnectClient": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "company": {
            "type": [
              "string",
              "null"
            ]
          },
          "externalId": {
            "type": [
              "string",
              "null"
            ]
          },
          "marketingOptIn": {
            "type": "boolean"
          },
          "clientType": {
            "type": "string",
            "enum": [
              "individual",
              "company"
            ]
          },
          "travelers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "adult",
                    "child",
                    "infant"
                  ]
                },
                "age": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "email": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "phone": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ConnectLead": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "enquiryNumber": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": "string"
          },
          "stage": {
            "type": "string"
          },
          "followUp": {
            "type": "boolean"
          },
          "clientId": {
            "type": [
              "string",
              "null"
            ]
          },
          "tripId": {
            "type": [
              "string",
              "null"
            ]
          },
          "externalId": {
            "type": [
              "string",
              "null"
            ]
          },
          "owner": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "email": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "destination": {
            "type": [
              "string",
              "null"
            ]
          },
          "travelDates": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "startDate": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "endDate": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "party": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "adults": {
                "type": "integer"
              },
              "children": {
                "type": "integer"
              },
              "childAges": {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              },
              "rooms": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "budget": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "amount": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "currency": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "notes": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ConnectTrip": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "leadId": {
            "type": [
              "string",
              "null"
            ]
          },
          "enquiryNumber": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": "string"
          },
          "stage": {
            "type": "string"
          },
          "destination": {
            "type": [
              "string",
              "null"
            ]
          },
          "travelDates": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "startDate": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "endDate": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "party": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "adults": {
                "type": "integer"
              },
              "children": {
                "type": "integer"
              },
              "childAges": {
                "type": "array",
                "items": {
                  "type": "integer"
                }
              },
              "rooms": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "budget": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "amount": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "currency": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "notes": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "guestNationality": {
            "type": [
              "string",
              "null"
            ]
          },
          "owner": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "email": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "proposal": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "status": {
                "type": "string"
              },
              "sentAt": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "itineraryApplied": {
            "type": "boolean",
            "description": "PATCH only: whether the itinerary replaced the draft proposal."
          },
          "itineraryNotAppliedReason": {
            "type": "string",
            "enum": [
              "advisor_working",
              "proposal_sent",
              "no_proposal",
              "update_failed"
            ],
            "description": "PATCH only, when an itinerary was sent but not applied."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ConnectError": {
        "type": "object",
        "required": [
          "statusCode",
          "code",
          "message"
        ],
        "properties": {
          "statusCode": {
            "type": "integer"
          },
          "code": {
            "type": "string",
            "enum": [
              "invalid_request",
              "idempotency_key_required",
              "identity_required",
              "invalid_itinerary",
              "lookup_field_required",
              "not_found",
              "client_exists",
              "identity_taken",
              "trip_not_open",
              "trip_closed",
              "stale_write",
              "idempotency_key_reused",
              "reason_required",
              "stage_not_allowed",
              "owner_not_member",
              "lead_create_failed"
            ]
          },
          "message": {
            "type": "string"
          },
          "clientId": {
            "type": "string"
          },
          "stage": {
            "type": "string"
          },
          "updatedAt": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "ConnectKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Connect-Key",
        "description": "The visible prefix of an active API key."
      },
      "ConnectTenant": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Connect-Tenant",
        "description": "Tenant slug bound to the key."
      },
      "ConnectSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Connect-Signature",
        "description": "`t=<unix>,v1=<hmac-sha256 of `<t>.<raw body>`>`."
      },
      "ConnectSignatureV2": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Connect-Signature",
        "description": "Records routes: `t=<unix>,v2=<hmac-sha256 of `<t>.<METHOD>.<path with query>.<raw body>`>`."
      }
    }
  }
}