Webhooks

Receive real-time notifications when events occur in your ledger.

Overview

Webhooks let you build integrations that react to events in Soledgic. When an event occurs (like a sale or payout), we send an HTTP POST request to your configured endpoint.

Configure webhooks in your Settings → Webhooks page.

Event Types

Subscribe to specific events or use * to receive all events.

EventDescription
sale.createdA new sale was recorded
sale.refundedA sale was refunded
payout.processedA payout was initiated
payout.executedA payout was completed
payout.failedA payout failed
creator.createdA new creator was added
period.closedAn accounting period was closed
statement.generatedA creator statement was generated

Webhook Payload

Every webhook POST includes these headers and a JSON body:

Headers

HeaderDescription
Content-Typeapplication/json
X-Soledgic-SignatureHMAC-SHA256 signature
X-Soledgic-EventEvent type (e.g., sale.created)

Example Payload

{
  "id": "evt_abc123",
  "type": "sale.created",
  "created_at": "2025-12-18T10:30:00Z",
  "livemode": true,
  "data": {
    "transaction_id": "txn_xyz789",
    "reference_id": "order_123",
    "creator_id": "creator_456",
    "amount": 2999,
    "currency": "USD",
    "breakdown": {
      "total": 29.99,
      "creator_amount": 23.99,
      "platform_amount": 6.00
    }
  }
}

Verifying Signatures

Always verify webhook signatures to ensure requests are from Soledgic. The signature is computed using HMAC-SHA256 with your webhook secret.

Important: Your webhook secret is shown only once when you create the endpoint. Store it securely.

Node.js

const crypto = require('crypto');

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

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your webhook handler
app.post('/webhooks/soledgic', (req, res) => {
  const signature = req.headers['x-soledgic-signature'];

  if (!verifyWebhookSignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  // Process the event
  const event = req.body;
  console.log('Received event:', event.type);

  res.status(200).send('OK');
});

Python

import hmac
import hashlib
import json

def verify_webhook_signature(payload, signature, secret):
    expected = 'sha256=' + hmac.new(
        secret.encode(),
        json.dumps(payload).encode(),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected)

# In your webhook handler (Flask example)
@app.route('/webhooks/soledgic', methods=['POST'])
def webhook():
    signature = request.headers.get('X-Soledgic-Signature')

    if not verify_webhook_signature(request.json, signature, WEBHOOK_SECRET):
        return 'Invalid signature', 401

    event = request.json
    print(f"Received event: {event['type']}")

    return 'OK', 200

Retry Policy

If your endpoint returns a non-2xx status code, we'll retry the webhook:

  • Up to 5 retry attempts
  • Exponential backoff: 1 min, 5 min, 30 min, 2 hours, 24 hours
  • After 5 failures, the delivery is marked as failed

You can view delivery attempts in the Webhooks settings page.

Best Practices

Return 200 quickly

Acknowledge receipt immediately, then process asynchronously

Handle duplicates

Use the event ID to deduplicate in case of retries

Verify signatures

Always validate the X-Soledgic-Signature header

Use HTTPS

Webhook endpoints must use HTTPS for security

Testing Webhooks

Use the "Test" button in your webhook settings to send a test event. This sends a sample payload to verify your endpoint is configured correctly.

For local development, use a tool like ngrok to expose your local server to the internet.