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
- Register Your Endpoint - Provide a webhook URL that your application maintains
- Receive Events - Lighthouse sends POST requests to your endpoint when events occur
- Authenticate Requests - Verify each webhook using HMAC signature validation
- 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: 23b08412a29bbe8625967e16c1a41dc9client_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-timestampheader
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-signatureheader
Example Result: 0ef94411f7e06fd28906719f3f1366585c50814040fec5f9fe0309a2e83e277b
Validate Signature
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-orderingCommon Events:
online-ordering.Order.created- New order placedonline-ordering.Order.updated- Order status changedonline-ordering.Menu.updated- Menu items or prices changed
- Name
POS Events- Description
Component:
posCommon Events:
pos.Check.created- New check openedpos.Check.updated- Check modifiedpos.Ticket.closed- Ticket finalizedpos.Payment.completed- Payment processed
- Name
Marketplace Events- Description
Component:
marketplaceCommon Events:
marketplace.Installation.created- Integration installedmarketplace.Installation.removed- Integration uninstalledmarketplace.Location.updated- Location settings changed
Example Event Handlers
Webhook Handler
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
versionfield 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 process400- Invalid request format401- Authentication failed500- 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/jsoncontent type - Be Publicly Accessible - Reachable from Lighthouse servers
Response Codes
| Status Code | Meaning | Lighthouse Action |
|---|---|---|
| 200-299 | Success | Event marked as delivered |
| 400-499 | Client error | Event not retried (except 408, 429) |
| 500-599 | Server error | Event retried with exponential backoff |
| Timeout | No response within 5s | Event retried |
Retry Behavior
When webhook delivery fails, Lighthouse implements exponential backoff:
- First retry: After 1 minute
- Second retry: After 5 minutes
- Third retry: After 15 minutes
- 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:
- Prepare Your Endpoint - Deploy a webhook handler that validates signatures and returns 200 OK
- Test Locally - Use tools like ngrok to test webhook handling during development
- Contact Shift4 Support - Provide your webhook URL and desired event types
- Configure Subscriptions - Support will configure subscriptions in your integration profile
- Monitor Initial Deliveries - Watch logs for first events and verify signature validation works
- 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.