Skip to main content

Overview

Webhooks let you react to events in real time instead of polling the API. This guide covers setting up a subscription, building an endpoint, and handling events reliably.

1. Create a webhook subscription

Register your endpoint URL and choose which events to listen for:
curl https://api.antonpayments.com/v1/webhooks \
  -X POST \
  -H "Authorization: Bearer ak_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhooks/anton",
    "events": [
      "payout.completed",
      "payout.failed",
      "payout.returned"
    ]
  }'
Response
{
  "data": {
    "id": "wbh_cng3q8s6ek9kc5qg1h4g",
    "url": "https://your-server.com/webhooks/anton",
    "events": ["payout.completed", "payout.failed", "payout.returned"],
    "status": "active",
    "created_at": "2026-02-14T10:00:00Z"
  }
}

2. Build your endpoint

Your webhook endpoint must:
  • Accept POST requests with a Content-Type: application/json body
  • Return a 2xx status code within 30 seconds
  • Be publicly accessible (not behind a VPN or firewall)
const express = require("express");
const app = express();

app.use(express.json());

app.post("/webhooks/anton", (req, res) => {
  const event = req.body;

  console.log(`Received event: ${event.type} for ${event.data.id}`);

  switch (event.type) {
    case "payout.completed":
      // Mark the invoice as paid in your system
      markInvoicePaid(event.data.reference);
      break;

    case "payout.failed":
      // Alert your team and flag for retry
      notifyPayoutFailed(event.data);
      break;

    case "payout.returned":
      // Credit the funds back in your system
      handlePayoutReturn(event.data);
      break;
  }

  // Always return 200 quickly — do heavy processing async
  res.status(200).json({ received: true });
});

app.listen(3000);

3. Handle failures gracefully

1

Return 200 immediately

Acknowledge receipt quickly. If processing takes time, queue it for async handling. Anton times out after 30 seconds and will retry.
2

Make it idempotent

You may receive the same event more than once (retries). Use the event.id to deduplicate — store processed event IDs and skip duplicates.
3

Handle out-of-order

Events might arrive out of order. A payout.completed could arrive before payout.processing. Use the created_at timestamp or the payout’s actual status to determine the true state.

4. Monitor deliveries

Check the delivery history for a webhook event:
curl https://api.antonpayments.com/v1/webhooks/events/evt_abc123/deliveries \
  -H "Authorization: Bearer ak_test_..."
This returns each delivery attempt with status codes, response times, and error details.

Testing locally

For local development, use a tunnel service to expose your local endpoint:
# Using ngrok
ngrok http 3000

# Your webhook URL will be something like:
# https://abc123.ngrok.io/webhooks/anton
Register this temporary URL as your webhook endpoint in sandbox.

Best practices

Respond fast

Return 200 within 5 seconds. Queue heavy processing for later.

Deduplicate

Track event IDs to prevent processing the same event twice.

Log everything

Log the full event payload for debugging and audit.

Set up alerts

Monitor for delivery failures — if your endpoint goes down, events queue up.