Sweet Spot API

Command Palette

Search for a command to run...

Webhooks Guide

Webhooks allow your application to receive real-time notifications when specific events occur in the leasing API. Instead of polling the API for changes, webhooks push event data to your application as events happen, enabling faster response times and more efficient integrations.

This guide covers how webhooks work, how to set them up, what events are available, and how to securely verify webhook requests. Before you begin, make sure you have your API key ready. If you need help with authentication, check out our Authentication guide.

How Webhooks Work

Webhooks allow you to receive real-time notifications when events occur in the Sweet Spot API. Instead of polling the API for changes, we send HTTP POST requests to your registered endpoint whenever a subscribed event happens.

Getting Started

  1. Create a Webhook: Register a webhook by providing your endpoint URL and selecting which events you want to receive
  2. Store Your Secret: When you create a webhook, you'll receive a secret key. Save this securely - you'll need it to verify incoming requests
  3. Receive Events: When subscribed events occur, we'll send HTTP POST requests to your endpoint with event data
  4. Verify & Process: Always verify the webhook signature before processing events to ensure they're authentic

Note: Your webhook endpoint must respond with a 2xx status code to acknowledge receipt. If your endpoint doesn't respond or returns an error, we'll automatically retry the delivery. Only active webhooks receive events - you can enable or disable webhooks at any time.

Available Events

You can subscribe to various event types to receive notifications about changes in your system. Events are organized by resource type (checkouts, customers, products, leases, payments).

Checkout Events

  • checkout.created - Fired when a new checkout is created
  • checkout.updated - Fired when a checkout is updated
  • checkout.completed - Fired when a checkout is completed
  • checkout.cancelled - Fired when a checkout is cancelled

Customer Events

  • customer.created - Fired when a new customer is created
  • customer.updated - Fired when customer information is updated
  • customer.credit_check_completed - Fired when a customer credit check completes

Product Events

  • product.created - Fired when a new product is created
  • product.updated - Fired when product information is updated
  • product.deleted - Fired when a product is deleted

Lease Events

  • lease.started - Fired when a lease begins
  • lease.ended - Fired when a lease ends

Payment Events

  • payment.received - Fired when a payment is received

Webhook Payload

When an event occurs, your webhook endpoint receives an HTTP POST request with a JSON payload containing the event data. The payload includes the event type, unique event ID, timestamp, and the event data.

Example Payload

JSON
{
  "id": "evt_1234567890",
  "type": "checkout.created",
  "data": {
    "id": "chk_123456",
    "state": "unpaid",
    "productVariantId": "pvar_123456",
    "customerId": "cust_123456",
    "createdAt": "2024-01-15T10:30:00Z"
  },
  "createdAt": "2024-01-15T10:30:00Z"
}

Note: The payload structure varies by event type. Each event includes an id,type, data object with event-specific information, and a createdAt timestamp.

Security

All webhook requests include security headers for verification. You should always verify the signature of incoming webhook requests to ensure they're coming from the Sweet Spot API and haven't been tampered with.

Webhook Headers

Every webhook request includes the following headers:

  • X-Webhook-Signature - HMAC-SHA256 signature in format sha256=hex_signature
  • X-Webhook-Timestamp - Unix timestamp when the request was signed
  • X-Webhook-Event-Type - The event type that triggered this webhook
  • X-Webhook-Event-ID - Unique identifier for this event occurrence

Signature Verification

The signature is computed as an HMAC-SHA256 hash of the timestamp and request body, using your webhook secret. The format is: HMAC-SHA256(timestamp + "." + body, secret)

To verify a webhook request:

  1. Extract the X-Webhook-Signature header (remove the sha256= prefix)
  2. Extract the X-Webhook-Timestamp header
  3. Reconstruct the signed payload: timestamp + "." + request_body
  4. Compute the expected signature using HMAC-SHA256 with your webhook secret
  5. Compare the signatures using constant-time comparison to prevent timing attacks
  6. Optionally check the timestamp to prevent replay attacks (recommended: reject requests older than 5 minutes)

Example: Verify Signature (Node.js)

JavaScript
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret, timestamp) {
  // Reconstruct the signed payload
  const signedPayload = `${timestamp}.${payload}`;
  
  // Compute the expected signature
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');
  
  // Extract the signature from the header (format: sha256=hex_signature)
  const receivedSignature = signature.replace('sha256=', '');
  
  // Compare signatures using constant-time comparison
  return crypto.timingSafeEqual(
    Buffer.from(expectedSignature),
    Buffer.from(receivedSignature)
  );
}

// Example usage in Express.js
app.post('/webhooks/sweetspot', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const timestamp = req.headers['x-webhook-timestamp'];
  const eventType = req.headers['x-webhook-event-type'];
  const eventId = req.headers['x-webhook-event-id'];
  
  const webhookSecret = process.env.WEBHOOK_SECRET;
  
  if (!verifyWebhookSignature(req.body, signature, webhookSecret, timestamp)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Check timestamp to prevent replay attacks (optional)
  const currentTime = Math.floor(Date.now() / 1000);
  const requestTime = parseInt(timestamp);
  if (Math.abs(currentTime - requestTime) > 300) { // 5 minutes tolerance
    return res.status(401).send('Request timestamp too old');
  }
  
  const event = JSON.parse(req.body);
  
  // Process the webhook event
  console.log('Received event:', eventType, eventId);
  
  res.status(200).send('OK');
});

Important: Always verify webhook signatures before processing events. Never trust webhook requests without verification, as they could be spoofed or tampered with. Store your webhook secret securely and never expose it in client-side code.

Best Practices

1. Always Verify Signatures

Never process webhook events without verifying the signature. This ensures the request is authentic and hasn't been tampered with.

2. Respond Quickly

Your webhook endpoint should respond with a 2xx status code as quickly as possible (ideally within 5 seconds). If you need to perform long-running operations, acknowledge the webhook first and process the event asynchronously.

3. Handle Duplicates

Webhooks may be delivered multiple times due to retries. Use the X-Webhook-Event-IDheader to deduplicate events and ensure idempotent processing.

4. Use HTTPS

Always use HTTPS endpoints for webhooks to ensure the payload is encrypted in transit. The API only acceptshttp:// or https:// URLs.

5. Test Your Endpoint

Use the test webhook endpoint to verify your webhook configuration and delivery before relying on it for production events.

6. Monitor Webhook Health

Monitor your webhook endpoint's response times and error rates. Ensure your endpoint is available and responding correctly to avoid missing events.