Subscriptions (Webhooks)

The Lighthouse API uses a subscription mechanism to notify third-party integrations in real-time when various events are triggered by Lighthouse components.

Overview

Subscriptions (webhooks) provide event-driven integration with the Lighthouse system. Instead of continuously polling the API for changes, your application receives HTTP POST notifications when relevant events occur.

How Subscriptions Work

  1. Register Your Endpoint - Provide a webhook URL that your application maintains
  2. Receive Events - Lighthouse sends POST requests to your endpoint when events occur
  3. Authenticate Requests - Verify each webhook using HMAC signature validation
  4. Parse and Process - Extract event data from the JSON payload and take action

Key Benefits

  • Real-Time Updates - Receive notifications instantly when events occur
  • Reduced API Calls - Eliminate constant polling, reducing rate limit usage
  • Event-Driven Architecture - Build reactive integrations that respond to changes
  • Reliable Delivery - Lighthouse retries failed webhook deliveries automatically

Authentication

HMAC Signature Validation

Every webhook request includes HMAC authentication headers that you must validate to ensure the request originated from Lighthouse:

  • Name
    x-access-key
    Description

    Your third-party client_id, same as used to authenticate outgoing API requests

  • Name
    x-timestamp
    Description

    Unix timestamp in seconds when the signature was generated. Use this to validate signature freshness.

  • Name
    x-signature
    Description

    HMAC-SHA256 signature generated by Lighthouse that you must verify matches your calculated signature

Validating Webhook Signatures

To verify a webhook request is authentic, generate your own signature and compare it to the x-signature header.

Example Credentials:

  • client_id: 23b08412a29bbe8625967e16c1a41dc9
  • client_secret: de17f1f0-4816-157b-97ae-eb4b0f656a1f

Signature Validation Steps

1. Extract Components

  • Use your client_id: 23b08412a29bbe8625967e16c1a41dc9
  • Method is always: POST
  • Extract path from webhook URL
  • Use the raw request body
  • Get timestamp from x-timestamp header

2. Combine String

Concatenate all components:

23b08412a29bbe8625967e16c1a41dc9POST/subscriptions/order{"event":{...},"payload":{...}}1554456360

3. Generate Signature

  • Create HMAC-SHA256 digest using client_secret
  • Encode digest as hexadecimal string
  • Compare to x-signature header

Example Result: 0ef94411f7e06fd28906719f3f1366585c50814040fec5f9fe0309a2e83e277b

Validate Signature

JavaScript
const crypto = require('crypto');

function validateWebhook(request) {
  const CLIENT_ID = '23b08412a29bbe8625967e16c1a41dc9';
  const CLIENT_SECRET = 'de17f1f0-4816-157b-97ae-eb4b0f656a1f';

  // Extract headers
  const receivedSignature = request.headers['x-signature'];
  const timestamp = request.headers['x-timestamp'];
  const accessKey = request.headers['x-access-key'];

  // Verify client ID matches
  if (accessKey !== CLIENT_ID) {
    return false;
  }

  // Extract path from request URL
  const urlPath = new URL(request.url).pathname;

  // Get raw request body
  const requestBody = JSON.stringify(request.body);

  // Combine components
  const combinedString =
    CLIENT_ID +
    'POST' +
    urlPath +
    requestBody +
    timestamp;

  // Generate signature
  const hmac = crypto.createHmac('sha256', CLIENT_SECRET);
  hmac.update(combinedString);
  const calculatedSignature = hmac.digest('hex');

  // Compare signatures
  return calculatedSignature === receivedSignature;
}

Event Structure

Webhook Request Format

All webhook notifications are sent as POST requests with JSON payloads containing two main sections: event metadata and payload data.

Request Method: POST

Content-Type: application/json

Endpoint: Your configured webhook URL

Each webhook contains comprehensive metadata about the event and the relevant data that changed.

Webhook Payload

{
  "event": {
    "component": "online-ordering",
    "resource": "Menu",
    "action": "updated",
    "name": "online-ordering.Menu.updated",
    "version": "v1",
    "subscriptionId": 1,
    "dispatchedAt": "2019-04-05T09:26:00.388Z"
  },
  "payload": {
    "locationId": 1
  }
}

Event Metadata

  • Name
    component
    Type
    string
    Description

    The Lighthouse component that dispatched this event

    Examples: pos, online-ordering, marketplace

  • Name
    resource
    Type
    string
    Description

    The resource type related to this event

    Examples: Menu, Order, Check, Ticket

  • Name
    action
    Type
    string
    Description

    The action that triggered the event

    Examples: created, updated, deleted, completed

  • Name
    name
    Type
    string
    Description

    Unique event name combining component, resource, and action

    Format: {component}.{resource}.{action}

    Example: online-ordering.Menu.updated

  • Name
    version
    Type
    string
    Description

    Event schema version for backward compatibility

    Example: v1, v2

  • Name
    subscriptionId
    Type
    integer
    Description

    Unique identifier for the subscription configuration

  • Name
    dispatchedAt
    Type
    string
    Description

    ISO 8601 timestamp when the event was dispatched

    Example: 2019-04-05T09:26:00.388Z

Event Payload

The payload object contains resource-specific data related to the event. The structure varies based on the component, resource, and action.

Note: Subscription payload structure depends on the specific event type. Refer to the endpoint documentation for detailed payload schemas.


Event Types

Common Event Patterns

Webhook events follow consistent naming patterns across different components:

  • Name
    Online Ordering Events
    Description

    Component: online-ordering

    Common Events:

    • online-ordering.Order.created - New order placed
    • online-ordering.Order.updated - Order status changed
    • online-ordering.Menu.updated - Menu items or prices changed
  • Name
    POS Events
    Description

    Component: pos

    Common Events:

    • pos.Check.created - New check opened
    • pos.Check.updated - Check modified
    • pos.Ticket.closed - Ticket finalized
    • pos.Payment.completed - Payment processed
  • Name
    Marketplace Events
    Description

    Component: marketplace

    Common Events:

    • marketplace.Installation.created - Integration installed
    • marketplace.Installation.removed - Integration uninstalled
    • marketplace.Location.updated - Location settings changed

Example Event Handlers

Webhook Handler

JavaScript
const express = require('express');
const app = express();

app.post('/webhooks/lighthouse', express.json(), (req, res) => {
  // Validate signature first
  if (!validateWebhook(req)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const { event, payload } = req.body;

  // Route to appropriate handler based on event name
  switch (event.name) {
    case 'online-ordering.Order.created':
      handleNewOrder(payload);
      break;

    case 'online-ordering.Order.updated':
      handleOrderUpdate(payload);
      break;

    case 'pos.Check.updated':
      handleCheckUpdate(payload);
      break;

    case 'marketplace.Installation.created':
      handleNewInstallation(payload);
      break;

    default:
      console.log(`Unhandled event: ${event.name}`);
  }

  // Always respond with 200 OK quickly
  res.status(200).json({ received: true });
});

function handleNewOrder(payload) {
  console.log('New order received:', payload);
  // Process order asynchronously
}

function handleOrderUpdate(payload) {
  console.log('Order updated:', payload);
  // Update order status in your system
}

function handleCheckUpdate(payload) {
  console.log('Check updated:', payload);
  // Sync check data
}

function handleNewInstallation(payload) {
  console.log('New installation:', payload);
  // Initialize integration for location
}

Best Practices

  • Name
    Validate Every Request
    Description

    Always validate the HMAC signature before processing webhook data. Reject requests with invalid signatures to prevent unauthorized access.

  • Name
    Respond Quickly
    Description

    Return a 200 OK response within 5 seconds. Process webhook data asynchronously to avoid timeouts.

  • Name
    Handle Idempotency
    Description

    Webhooks may be delivered multiple times. Use event IDs or timestamps to detect and handle duplicate deliveries.

  • Name
    Implement Retry Logic
    Description

    If your webhook processing fails, store the event for later retry. Lighthouse will retry delivery, but you should have a backup strategy.

  • Name
    Log All Webhooks
    Description

    Log received webhooks for debugging and audit purposes. Include timestamp, event name, and processing status.

  • Name
    Monitor Webhook Health
    Description

    Track webhook delivery success rates, processing times, and error patterns. Alert on anomalies.

  • Name
    Version Handling
    Description

    Check the version field and handle schema changes gracefully. Test with both old and new versions during transitions.

  • Name
    Secure Your Endpoint
    Description

    Use HTTPS for your webhook URL. Consider IP whitelisting and rate limiting to protect against abuse.

  • Name
    Error Handling
    Description

    Return appropriate HTTP status codes:

    • 200 - Successfully received and will process
    • 400 - Invalid request format
    • 401 - Authentication failed
    • 500 - Internal error (Lighthouse will retry)
  • Name
    Test Thoroughly
    Description

    Set up a test webhook endpoint during development. Request test events from Lighthouse support to validate your implementation.


Webhook Endpoint Requirements

Technical Requirements

Your webhook endpoint must:

  • Accept POST Requests - All webhooks are sent via HTTP POST
  • Support HTTPS - Production webhooks require SSL/TLS
  • Validate Signatures - Check HMAC signature on every request
  • Respond Quickly - Return 2xx status within 5 seconds
  • Handle JSON - Parse application/json content type
  • Be Publicly Accessible - Reachable from Lighthouse servers

Response Codes

Status CodeMeaningLighthouse Action
200-299SuccessEvent marked as delivered
400-499Client errorEvent not retried (except 408, 429)
500-599Server errorEvent retried with exponential backoff
TimeoutNo response within 5sEvent retried

Retry Behavior

When webhook delivery fails, Lighthouse implements exponential backoff:

  1. First retry: After 1 minute
  2. Second retry: After 5 minutes
  3. Third retry: After 15 minutes
  4. Additional retries: Up to 24 hours

After maximum retries, the event is marked as failed and logged for manual review.


Setting Up Subscriptions

To configure webhooks for your integration:

  1. Prepare Your Endpoint - Deploy a webhook handler that validates signatures and returns 200 OK
  2. Test Locally - Use tools like ngrok to test webhook handling during development
  3. Contact Shift4 Support - Provide your webhook URL and desired event types
  4. Configure Subscriptions - Support will configure subscriptions in your integration profile
  5. Monitor Initial Deliveries - Watch logs for first events and verify signature validation works
  6. Go Live - Once tested, deploy to production and update subscription URL

For assistance with webhook configuration, contact Shift4 integration support with your integration details and webhook requirements.

Was this page helpful?