Manage Webhooks

webhooks.list.subtitle

Last Updated: March 8, 2026

Overview

Webhooks allow Pause POS merchants to receive real-time notifications when events happen in their POS system. Merchants can configure custom HTTP endpoints to receive JSON payloads.

Order Completed

When a POS order is synced

Order Refunded

When an order is refunded or credit note created

Stock Low

When product stock drops below minimum threshold

Shift Closed

When a cash drawer shift is closed

API Integration

Available Functions

All webhook functions are already exported from `lib/api.ts` and ready to use:

lib/api.ts - Webhook Functions
// Fetch all webhooks for current tenant
fetchWebhooks(): Promise<ApiWebhook[]>

// Get single webhook details
fetchWebhookById(id: number): Promise<ApiWebhook>

// Create new webhook (returns secret)
createWebhook(data: CreateWebhookInput): Promise<ApiWebhook & { secret: string }>

// Update webhook (events, headers, name)
updateWebhook(id: number, data: Partial<CreateWebhookInput>): Promise<ApiWebhook>

// Delete webhook
deleteWebhook(id: number): Promise<void>

// Rotate signing secret
rotateWebhookSecret(id: number): Promise<ApiWebhook & { secret: string }>

// Fetch delivery attempts log
fetchWebhookDeliveries(id: number, limit?: number): Promise<ApiWebhookDelivery[]>

// Manually retry a failed delivery
redeliverWebhook(webhookId: number, deliveryId: number): Promise<void>

TypeScript Types

TypeScript Interfaces
interface ApiWebhook {
    id: number;
    tenant_id: string;
    name: string;
    url: string;
    events: string; // JSON array: ["order.completed","stock.low"]
    secret?: string; // Only shown on creation
    headers?: string; // Custom headers as JSON
    is_active: boolean;
    created_at: string;
    updated_at: string;
}

interface ApiWebhookDelivery {
    id: number;
    tenant_id: string;
    webhook_id: number;
    event_type: string;
    payload: string; // JSON payload sent
    response_status: number; // HTTP status code
    response_body: string; // Response from endpoint
    attempt_count: number;
    next_retry_at: string | null;
    status: 'pending' | 'delivered' | 'failed' | 'retrying';
    created_at: string;
    updated_at: string;
}

interface CreateWebhookInput {
    name: string;
    url: string;
    events: string[]; // Array of event types
    headers?: Record<string, string>;
}

Example Webhook Payload

This is an example of what your webhook endpoint will receive:

Example order.completed Event
{
  "id": "delivery-uuid",
  "event": "order.completed",
  "tenant_id": "tenant-uuid",
  "created_at": "2026-03-08T10:30:00Z",
  "data": {
    "order_id": 123,
    "invoice_number": "TAXINV-2026-000001",
    "total_amount": 150.00,
    "items_count": 3
  }
}

Implementation Guide

Secret Handling

The webhook secret is shown only once after creation. You should:

  • Store the secret securely on your backend
  • Use it to verify webhook signatures via HMAC-SHA256
  • Rotate the secret periodically for security
  • Never expose the secret in client-side code

Webhook URL Requirements

  • Must use HTTPS (encrypted connection required)
  • Must return HTTP 2xx status to confirm delivery
  • Should respond within 30 seconds
  • Timeouts or errors trigger automatic retries

Automatic Retry Logic

Failed deliveries are automatically retried on this schedule:

Retry Schedule
Attempt 1: Immediate failure
Attempt 2: 1 minute later
Attempt 3: 5 minutes later
Attempt 4: 30 minutes later
Max attempts: 4 (then marked as failed)

Testing Your Webhooks

Recommended: webhook.site

Use webhook.site for free testing and debugging:

  1. Visit webhook.site
  2. Copy your unique URL
  3. Paste it in your webhook configuration
  4. Trigger an event (e.g., complete an order)
  5. See the request in real-time
Example Webhook Endpoint
// Example webhook endpoint (Node.js)
import crypto from 'crypto';

app.post('/webhooks/pause', (req, res) => {
  const signature = req.headers['x-pause-signature'];
  const payload = JSON.stringify(req.body);

  // Verify signature
  const hash = crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET)
    .update(payload)
    .digest('hex');

  if (hash !== signature) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  // Process webhook
  const { event, data } = req.body;

  switch (event) {
    case 'order.completed':
      // Handle order completion
      break;
    case 'stock.low':
      // Handle low stock alert
      break;
  }

  // Return 200 OK to confirm delivery
  res.json({ success: true });
});

Best Practices

Always verify signatures

Validate the X-Pause-Signature header using HMAC-SHA256 to ensure the webhook came from Pause POS.

Respond quickly

Your webhook endpoint should respond within 30 seconds. Queue long-running tasks asynchronously.

Handle duplicates

Webhooks may be delivered multiple times. Use idempotency keys (event ID) to prevent duplicate processing.

Use HTTPS only

All webhook URLs must use HTTPS to protect sensitive business data in transit.

Need Help?

Our support team is here to help you integrate webhooks.