Webhooks
Receive signed callbacks when invoices change status — no polling required.
Delivery
Set a public https callback_url when creating an invoice (private, localhost, and cloud-metadata hosts are rejected — invalid URLs return 400 INVALID_CALLBACK at create time). On each status transition, swp.gg POSTs JSON with X-Swp-Signature, optional replay-safe X-Swp-Signature-V2 + X-Swp-Timestamp, and User-Agent: swp.gg-webhooks/1.0.
Signature
Verify with HMAC-SHA256(rawBody, secret) where secret is the full whsec_… string from the dashboard (API Keys → Webhook signing secret → Reveal). Use that value as the HMAC key — do not add another whsec_ prefix.
const crypto = require("crypto");
function verifyWebhook(rawBody, header, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
const received = header.replace("sha256=", "");
return crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(received, "hex"),
);
}
// Recommended: also verify X-Swp-Signature-V2 over `${timestamp}.${rawBody}`
// and reject if |now - X-Swp-Timestamp| > 5 minutes.Events
invoice.confirming— payment seen on-chain; waiting for confirmationsinvoice.paid— confirmed within accuracy and creditedinvoice.partially_paid— confirmed but below the due amountinvoice.expired— lifetime ended without a full payment
Payload fields include track_id, status, order_id, amounts, pay_currency, address, tx_hash, and confirmation counts.
Reliability
Delivery is best-effort (~8s timeout, no automatic retries). Make your endpoint idempotent and reconcile with GET /api/v1/invoice/{track_id}?refresh=1 when needed.
Full field reference: API documentation.