{
  "info": {
    "name": "HolidayOS Connect (your-tenant-slug)",
    "description": "HolidayOS Connect 1.0. Set connectKey and connectSecret, then send. Full reference: https://holidayos.ai/developers/connect",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "apiOrigin",
      "value": "https://api.new.holidayos.ai"
    },
    {
      "key": "tenantSlug",
      "value": "your-tenant-slug"
    },
    {
      "key": "connectKey",
      "value": "",
      "type": "string"
    },
    {
      "key": "connectSecret",
      "value": "",
      "type": "secret"
    }
  ],
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// Signs the request body with the Connect API key secret.",
          "// Set connectKey / connectSecret as collection or environment variables.",
          "const rawBody = pm.request.body ? pm.request.body.raw : '';",
          "const timestamp = Math.floor(Date.now() / 1000);",
          "const digest = CryptoJS.HmacSHA256(",
          "  timestamp + '.' + rawBody,",
          "  pm.variables.get('connectSecret'),",
          ").toString(CryptoJS.enc.Hex);",
          "pm.request.headers.upsert({ key: 'X-Connect-Key', value: pm.variables.get('connectKey') });",
          "pm.request.headers.upsert({ key: 'X-Connect-Tenant', value: pm.variables.get('tenantSlug') });",
          "pm.request.headers.upsert({",
          "  key: 'X-Connect-Signature',",
          "  value: 't=' + timestamp + ',v1=' + digest,",
          "});"
        ]
      }
    }
  ],
  "item": [
    {
      "name": "contact.identified",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('accepted', function () {",
              "  pm.response.to.have.status(200);",
              "  const body = pm.response.json();",
              "  pm.expect(body.failed, 'failed count').to.eql(0);",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": {
          "raw": "{{apiOrigin}}/api/v1/crm/connect/events",
          "host": [
            "{{apiOrigin}}"
          ],
          "path": [
            "api",
            "v1",
            "crm",
            "connect",
            "events"
          ]
        },
        "description": "A traveller identified themselves — signed in, or filled in a form.\n\nUpserts the contact and appends a timeline entry. No enquiry is opened.",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"events\": [\n    {\n      \"specVersion\": \"1.0\",\n      \"eventId\": \"evt_contact_identified_1\",\n      \"eventType\": \"contact.identified\",\n      \"occurredAt\": \"2026-08-23T09:15:00Z\",\n      \"tenant\": \"your-tenant-slug\",\n      \"origin\": \"source-system\",\n      \"actor\": {\n        \"type\": \"contact\",\n        \"email\": \"traveler@example.com\",\n        \"name\": \"Ana Silva\",\n        \"phone\": \"+60123456789\"\n      },\n      \"payload\": {\n        \"destination\": \"Bali\"\n      }\n    }\n  ]\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      }
    },
    {
      "name": "contact.updated",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('accepted', function () {",
              "  pm.response.to.have.status(200);",
              "  const body = pm.response.json();",
              "  pm.expect(body.failed, 'failed count').to.eql(0);",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": {
          "raw": "{{apiOrigin}}/api/v1/crm/connect/events",
          "host": [
            "{{apiOrigin}}"
          ],
          "path": [
            "api",
            "v1",
            "crm",
            "connect",
            "events"
          ]
        },
        "description": "A known traveller's details changed on your system.\n\nPatches the existing contact's fields and appends a timeline entry.",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"events\": [\n    {\n      \"specVersion\": \"1.0\",\n      \"eventId\": \"evt_contact_updated_1\",\n      \"eventType\": \"contact.updated\",\n      \"occurredAt\": \"2026-08-23T09:15:00Z\",\n      \"tenant\": \"your-tenant-slug\",\n      \"origin\": \"source-system\",\n      \"actor\": {\n        \"type\": \"contact\",\n        \"email\": \"traveler@example.com\",\n        \"name\": \"Ana Silva\",\n        \"phone\": \"+60123456789\"\n      },\n      \"payload\": {\n        \"destination\": \"Bali\"\n      }\n    }\n  ]\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      }
    },
    {
      "name": "enquiry.submitted",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('accepted', function () {",
              "  pm.response.to.have.status(200);",
              "  const body = pm.response.json();",
              "  pm.expect(body.failed, 'failed count').to.eql(0);",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": {
          "raw": "{{apiOrigin}}/api/v1/crm/connect/events",
          "host": [
            "{{apiOrigin}}"
          ],
          "path": [
            "api",
            "v1",
            "crm",
            "connect",
            "events"
          ]
        },
        "description": "A traveller asked for a quote. This is the event most integrations send.\n\nUpserts the contact, appends a timeline entry, and opens an enquiry at stage `inquiry` with a trip workspace in the inbox.",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"events\": [\n    {\n      \"specVersion\": \"1.0\",\n      \"eventId\": \"evt_enquiry_submitted_1\",\n      \"eventType\": \"enquiry.submitted\",\n      \"occurredAt\": \"2026-08-23T09:15:00Z\",\n      \"tenant\": \"your-tenant-slug\",\n      \"origin\": \"source-system\",\n      \"actor\": {\n        \"type\": \"contact\",\n        \"email\": \"traveler@example.com\",\n        \"name\": \"Ana Silva\",\n        \"phone\": \"+60123456789\"\n      },\n      \"payload\": {\n        \"destination\": \"Bali\",\n        \"travelDates\": {\n          \"startDate\": \"2026-11-04\",\n          \"endDate\": \"2026-11-10\"\n        },\n        \"party\": {\n          \"adults\": 3,\n          \"children\": 0,\n          \"rooms\": 1\n        },\n        \"message\": \"Customer requested advisor pricing before checkout.\"\n      }\n    }\n  ]\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      }
    },
    {
      "name": "trip.planning_started",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('accepted', function () {",
              "  pm.response.to.have.status(200);",
              "  const body = pm.response.json();",
              "  pm.expect(body.failed, 'failed count').to.eql(0);",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": {
          "raw": "{{apiOrigin}}/api/v1/crm/connect/events",
          "host": [
            "{{apiOrigin}}"
          ],
          "path": [
            "api",
            "v1",
            "crm",
            "connect",
            "events"
          ]
        },
        "description": "The traveller began building a trip on your site.\n\nTimeline only — a planning signal carries no enquiry obligation.",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"events\": [\n    {\n      \"specVersion\": \"1.0\",\n      \"eventId\": \"evt_trip_planning_started_1\",\n      \"eventType\": \"trip.planning_started\",\n      \"occurredAt\": \"2026-08-23T09:15:00Z\",\n      \"tenant\": \"your-tenant-slug\",\n      \"origin\": \"source-system\",\n      \"actor\": {\n        \"type\": \"contact\",\n        \"email\": \"traveler@example.com\",\n        \"name\": \"Ana Silva\",\n        \"phone\": \"+60123456789\"\n      },\n      \"payload\": {\n        \"destination\": \"Bali\"\n      }\n    }\n  ]\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      }
    },
    {
      "name": "trip.draft_updated",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('accepted', function () {",
              "  pm.response.to.have.status(200);",
              "  const body = pm.response.json();",
              "  pm.expect(body.failed, 'failed count').to.eql(0);",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": {
          "raw": "{{apiOrigin}}/api/v1/crm/connect/events",
          "host": [
            "{{apiOrigin}}"
          ],
          "path": [
            "api",
            "v1",
            "crm",
            "connect",
            "events"
          ]
        },
        "description": "The traveller changed their in-progress trip draft.\n\nTimeline only.",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"events\": [\n    {\n      \"specVersion\": \"1.0\",\n      \"eventId\": \"evt_trip_draft_updated_1\",\n      \"eventType\": \"trip.draft_updated\",\n      \"occurredAt\": \"2026-08-23T09:15:00Z\",\n      \"tenant\": \"your-tenant-slug\",\n      \"origin\": \"source-system\",\n      \"actor\": {\n        \"type\": \"contact\",\n        \"email\": \"traveler@example.com\",\n        \"name\": \"Ana Silva\",\n        \"phone\": \"+60123456789\"\n      },\n      \"payload\": {\n        \"destination\": \"Bali\"\n      }\n    }\n  ]\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      }
    },
    {
      "name": "quote.requested",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('accepted', function () {",
              "  pm.response.to.have.status(200);",
              "  const body = pm.response.json();",
              "  pm.expect(body.failed, 'failed count').to.eql(0);",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": {
          "raw": "{{apiOrigin}}/api/v1/crm/connect/events",
          "host": [
            "{{apiOrigin}}"
          ],
          "path": [
            "api",
            "v1",
            "crm",
            "connect",
            "events"
          ]
        },
        "description": "A price was fetched — often automatically, while the visitor browses.\n\nTimeline only. Deliberately does not open an enquiry: only an explicit `enquiry.submitted` may create or advance one.",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"events\": [\n    {\n      \"specVersion\": \"1.0\",\n      \"eventId\": \"evt_quote_requested_1\",\n      \"eventType\": \"quote.requested\",\n      \"occurredAt\": \"2026-08-23T09:15:00Z\",\n      \"tenant\": \"your-tenant-slug\",\n      \"origin\": \"source-system\",\n      \"actor\": {\n        \"type\": \"contact\",\n        \"email\": \"traveler@example.com\",\n        \"name\": \"Ana Silva\",\n        \"phone\": \"+60123456789\"\n      },\n      \"payload\": {\n        \"destination\": \"Bali\"\n      }\n    }\n  ]\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      }
    },
    {
      "name": "booking.started",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('accepted', function () {",
              "  pm.response.to.have.status(200);",
              "  const body = pm.response.json();",
              "  pm.expect(body.failed, 'failed count').to.eql(0);",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": {
          "raw": "{{apiOrigin}}/api/v1/crm/connect/events",
          "host": [
            "{{apiOrigin}}"
          ],
          "path": [
            "api",
            "v1",
            "crm",
            "connect",
            "events"
          ]
        },
        "description": "The traveller entered checkout.\n\nAdvances the open enquiry to `proposal_approved` if that is further along than its current stage. Never regresses a stage.",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"events\": [\n    {\n      \"specVersion\": \"1.0\",\n      \"eventId\": \"evt_booking_started_1\",\n      \"eventType\": \"booking.started\",\n      \"occurredAt\": \"2026-08-23T09:15:00Z\",\n      \"tenant\": \"your-tenant-slug\",\n      \"origin\": \"source-system\",\n      \"actor\": {\n        \"type\": \"contact\",\n        \"email\": \"traveler@example.com\",\n        \"name\": \"Ana Silva\",\n        \"phone\": \"+60123456789\"\n      },\n      \"payload\": {\n        \"destination\": \"Bali\"\n      }\n    }\n  ]\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      }
    },
    {
      "name": "booking.abandoned",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('accepted', function () {",
              "  pm.response.to.have.status(200);",
              "  const body = pm.response.json();",
              "  pm.expect(body.failed, 'failed count').to.eql(0);",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": {
          "raw": "{{apiOrigin}}/api/v1/crm/connect/events",
          "host": [
            "{{apiOrigin}}"
          ],
          "path": [
            "api",
            "v1",
            "crm",
            "connect",
            "events"
          ]
        },
        "description": "The traveller left checkout without completing.\n\nFlags the open enquiry for follow-up. Leaves its stage untouched.",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"events\": [\n    {\n      \"specVersion\": \"1.0\",\n      \"eventId\": \"evt_booking_abandoned_1\",\n      \"eventType\": \"booking.abandoned\",\n      \"occurredAt\": \"2026-08-23T09:15:00Z\",\n      \"tenant\": \"your-tenant-slug\",\n      \"origin\": \"source-system\",\n      \"actor\": {\n        \"type\": \"contact\",\n        \"email\": \"traveler@example.com\",\n        \"name\": \"Ana Silva\",\n        \"phone\": \"+60123456789\"\n      },\n      \"payload\": {\n        \"destination\": \"Bali\"\n      }\n    }\n  ]\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      }
    },
    {
      "name": "booking.completed",
      "event": [
        {
          "listen": "test",
          "script": {
            "type": "text/javascript",
            "exec": [
              "pm.test('accepted', function () {",
              "  pm.response.to.have.status(200);",
              "  const body = pm.response.json();",
              "  pm.expect(body.failed, 'failed count').to.eql(0);",
              "});"
            ]
          }
        }
      ],
      "request": {
        "method": "POST",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          }
        ],
        "url": {
          "raw": "{{apiOrigin}}/api/v1/crm/connect/events",
          "host": [
            "{{apiOrigin}}"
          ],
          "path": [
            "api",
            "v1",
            "crm",
            "connect",
            "events"
          ]
        },
        "description": "The traveller paid and the booking is confirmed.\n\nForces the enquiry to stage `trip_booked`.",
        "body": {
          "mode": "raw",
          "raw": "{\n  \"events\": [\n    {\n      \"specVersion\": \"1.0\",\n      \"eventId\": \"evt_booking_completed_1\",\n      \"eventType\": \"booking.completed\",\n      \"occurredAt\": \"2026-08-23T09:15:00Z\",\n      \"tenant\": \"your-tenant-slug\",\n      \"origin\": \"source-system\",\n      \"actor\": {\n        \"type\": \"contact\",\n        \"email\": \"traveler@example.com\",\n        \"name\": \"Ana Silva\",\n        \"phone\": \"+60123456789\"\n      },\n      \"payload\": {\n        \"destination\": \"Bali\"\n      }\n    }\n  ]\n}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        }
      }
    }
  ]
}