Skip to main content
GuestIQ integrations allow you to push real-time guest intelligence to your existing loyalty platforms, CRMs, and marketing systems. Every signal, segment change, and guest event can flow to your systems automatically.

Webhooks

Receive real-time events from GuestIQ via HTTP webhooks.

Register Webhook

mutation RegisterWebhook($input: RegisterWebhookInput!) {
  registerWebhook(input: $input) {
    webhookId
    url
    events
    status
    secret
  }
}

Input

input RegisterWebhookInput {
  chainId: String!
  url: String!
  events: [WebhookEvent!]!
  secret: String              # Optional: we'll generate one if not provided
  headers: [HeaderInput!]     # Custom headers to include
}

input HeaderInput {
  name: String!
  value: String!
}

enum WebhookEvent {
  # Guest events
  GUEST_IDENTIFIED
  GUEST_PROFILE_UPDATED
  GUEST_MERGED

  # Segment events
  SEGMENT_ENTERED
  SEGMENT_EXITED

  # Signal events (high volume)
  SIGNAL_RECEIVED
  SESSION_STARTED
  SESSION_ENDED

  # Order events
  ORDER_COMPLETED
  CART_ABANDONED

  # Lifecycle events
  GUEST_AT_RISK
  GUEST_CHURNED
  GUEST_REACTIVATED
}

Example

mutation RegisterWebhook {
  registerWebhook(input: {
    chainId: "honeygrow"
    url: "https://api.yourapp.com/webhooks/guestiq"
    events: [
      GUEST_IDENTIFIED
      SEGMENT_ENTERED
      SEGMENT_EXITED
      ORDER_COMPLETED
      GUEST_AT_RISK
    ]
    headers: [
      { name: "X-Api-Key", value: "your-api-key" }
    ]
  }) {
    webhookId
    url
    events
    status
    secret
  }
}

Webhook Payload Format

All webhooks are delivered as HTTP POST requests with JSON payloads:
{
  "id": "evt_123abc",
  "type": "SEGMENT_ENTERED",
  "timestamp": "2026-01-24T12:30:00Z",
  "chainId": "honeygrow",
  "data": {
    "guestId": "guest_abc123",
    "segmentId": "seg_high_value",
    "segmentName": "high-value-loyalists",
    "previousSegments": ["frequent-visitor", "customizer"],
    "currentSegments": ["frequent-visitor", "customizer", "high-value-loyalists"]
  }
}

Headers

HeaderDescription
X-GuestIQ-SignatureHMAC-SHA256 signature for verification
X-GuestIQ-EventEvent type
X-GuestIQ-Delivery-IDUnique delivery ID for idempotency
X-GuestIQ-TimestampEvent timestamp

Signature Verification

Verify webhook authenticity using the signature:
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(`sha256=${expected}`)
  );
}

Webhook Event Payloads

GUEST_IDENTIFIED

{
  "type": "GUEST_IDENTIFIED",
  "data": {
    "guestId": "guest_abc123",
    "sessionId": "sess_xyz789",
    "identifiedVia": "LOYALTY_ID",
    "confidence": 0.98,
    "isReturning": true,
    "segments": {
      "primary": ["wheat-free", "high-protein"],
      "compound": ["wheat-free+high-protein"]
    },
    "cohorts": ["health-conscious-regulars"]
  }
}

SEGMENT_ENTERED / SEGMENT_EXITED

{
  "type": "SEGMENT_ENTERED",
  "data": {
    "guestId": "guest_abc123",
    "segmentId": "seg_frequent_visitor",
    "segmentName": "frequent-visitor",
    "segmentType": "PRIMARY",
    "trigger": "visit_count_threshold",
    "currentSegments": ["wheat-free", "high-protein", "frequent-visitor"]
  }
}

ORDER_COMPLETED

{
  "type": "ORDER_COMPLETED",
  "data": {
    "guestId": "guest_abc123",
    "sessionId": "sess_xyz789",
    "orderId": "order_123",
    "restaurantId": "loc_philly_walnut",
    "orderTotal": 24.50,
    "itemCount": 3,
    "items": [
      {
        "dishId": "dish_001",
        "dishName": "Power Bowl",
        "quantity": 1,
        "price": 14.50,
        "customized": true
      }
    ],
    "segments": ["wheat-free", "high-protein", "customizer"]
  }
}

GUEST_AT_RISK

{
  "type": "GUEST_AT_RISK",
  "data": {
    "guestId": "guest_abc123",
    "riskLevel": "MEDIUM",
    "daysSinceLastVisit": 21,
    "previousVisitFrequency": 2.5,
    "predictedChurnProbability": 0.35,
    "recommendedActions": [
      "Send win-back offer",
      "Highlight new menu items matching preferences"
    ],
    "guestSegments": ["wheat-free", "high-protein", "was-frequent-visitor"]
  }
}

List Webhooks

query ListWebhooks($chainId: String!) {
  webhooks(chainId: $chainId) {
    webhookId
    url
    events
    status
    createdAt
    lastDelivery {
      timestamp
      status
      responseCode
    }
  }
}

Update Webhook

mutation UpdateWebhook($webhookId: ID!, $input: UpdateWebhookInput!) {
  updateWebhook(webhookId: $webhookId, input: $input) {
    webhookId
    url
    events
    status
  }
}

Delete Webhook

mutation DeleteWebhook($webhookId: ID!) {
  deleteWebhook(webhookId: $webhookId) {
    success
  }
}

Batch Export

For systems that prefer batch processing over real-time webhooks, schedule recurring exports.

Create Export Schedule

mutation CreateExportSchedule($input: CreateExportScheduleInput!) {
  createExportSchedule(input: $input) {
    scheduleId
    frequency
    destination
    dataTypes
    nextRunAt
  }
}

Input

input CreateExportScheduleInput {
  chainId: String!
  frequency: ExportFrequency!
  destination: ExportDestinationInput!
  dataTypes: [ExportDataType!]!
  filters: ExportFilterInput
}

enum ExportFrequency {
  HOURLY
  DAILY
  WEEKLY
}

input ExportDestinationInput {
  type: DestinationType!
  s3Bucket: String           # For S3
  s3Prefix: String
  sftpHost: String           # For SFTP
  sftpPath: String
  webhookUrl: String         # For webhook delivery
}

enum DestinationType {
  S3
  SFTP
  WEBHOOK
}

enum ExportDataType {
  GUEST_PROFILES
  SEGMENTS
  SIGNALS
  ORDERS
}

Example

mutation CreateExportSchedule {
  createExportSchedule(input: {
    chainId: "honeygrow"
    frequency: DAILY
    destination: {
      type: S3
      s3Bucket: "your-data-bucket"
      s3Prefix: "guestiq/daily/"
    }
    dataTypes: [GUEST_PROFILES, SEGMENTS]
    filters: {
      modifiedSince: "LAST_RUN"
    }
  }) {
    scheduleId
    nextRunAt
  }
}

Direct Integrations

GuestIQ offers native integrations with popular loyalty and marketing platforms.

Supported Platforms

PlatformTypeStatus
PunchhLoyaltyAvailable
ThanxLoyaltyAvailable
PaytronixLoyaltyAvailable
OloOrderingAvailable
BrazeMarketingAvailable
KlaviyoMarketingAvailable
SegmentCDPAvailable
SalesforceCRMComing Soon

Configure Integration

mutation ConfigureIntegration($input: ConfigureIntegrationInput!) {
  configureIntegration(input: $input) {
    integrationId
    platform
    status
    syncedDataTypes
    lastSyncAt
  }
}

Input

input ConfigureIntegrationInput {
  chainId: String!
  platform: IntegrationPlatform!
  credentials: IntegrationCredentialsInput!
  syncConfig: SyncConfigInput!
}

input IntegrationCredentialsInput {
  apiKey: String
  apiSecret: String
  accountId: String
  # Platform-specific fields
}

input SyncConfigInput {
  syncGuests: Boolean!
  syncSegments: Boolean!
  syncSignals: Boolean!
  syncOrders: Boolean!
  realTime: Boolean!          # Real-time vs batch sync
}

Example: Punchh Integration

mutation ConfigurePunchh {
  configureIntegration(input: {
    chainId: "honeygrow"
    platform: PUNCHH
    credentials: {
      apiKey: "pk_punchh_xxx"
      apiSecret: "sk_punchh_xxx"
      accountId: "honeygrow_punchh"
    }
    syncConfig: {
      syncGuests: true
      syncSegments: true
      syncSignals: false
      syncOrders: true
      realTime: true
    }
  }) {
    integrationId
    platform
    status
  }
}

Best Practices

Start with Key Events

Don’t subscribe to all events initially. Start with SEGMENT_ENTERED, ORDER_COMPLETED, and GUEST_AT_RISK for immediate value.

Handle Retries

GuestIQ retries failed webhooks with exponential backoff. Implement idempotency using the delivery ID.

Use Batch for Analytics

For analytics and reporting, use batch exports instead of processing every signal webhook.

Verify Signatures

Always verify webhook signatures in production to ensure events are from GuestIQ.

Rate Limits

Integration TypeLimit
Webhooks10,000 events/minute
Batch Export1 export/hour per schedule
Direct IntegrationsPlatform-dependent
High-volume events like SIGNAL_RECEIVED can generate significant webhook traffic. Consider using batch exports for signal data unless you need real-time processing.