Webhooks

Webhooks are the asynchronous source of truth. Yusker POSTs an event to your endpoint whenever a transfer settles, a payout is paid, a dispute opens, or a merchant's status changes.

PreviewThe Payments API is in a design-partner preview and not yet publicly callable — endpoints and shapes may change. Request access to join the program. Building a venue integration today? Use the live Venue API.

Register an endpoint

Configure an HTTPS URL in the dashboard (or via API). Yusker signs each delivery so you can verify it came from Yusker.

curl -u "$YUSKER_KEY" "$YUSKER_BASE/webhooks" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://api.yourapp.com/webhooks/yusker", "enabled_events": ["transfer.*", "dispute.*"] }'

Event types

transfer.succeeded
eventoptional
A sale captured and is settling. Close the check here.
transfer.failed
eventoptional
A sale was declined or reversed. No funds moved.
payout.paid
eventoptional
Settlement funds were paid out to a merchant's bank.
dispute.opened
eventoptional
A cardholder disputed a transfer (chargeback). Respond with evidence.
merchant.updated
eventoptional
A merchant's onboarding or processing state changed.

Event payload

{
  "id": "EVxxxx",
  "type": "transfer.succeeded",
  "created_at": "2026-07-01T14:38:25Z",
  "transfer": {
    "id": "TRxxxx",
    "state": "SUCCEEDED",
    "merchant": "MUxxxx",
    "amount": 5000,
    "fee": 175,
    "currency": "CAD",
    "tags": { "check_id": "4823" }
  }
}

Verify the signature

Each delivery carries a signature derived from your webhook secret. Verify it before acting, and reject anything that doesn't match — an unverified webhook must never move money.

import crypto from "crypto";

function verifyYuskerSignature(req) {
  const sig = req.headers["yusker-signature"];
  const expected = crypto
    .createHmac("sha256", process.env.YUSKER_WEBHOOK_SECRET)
    .update(req.rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
Be idempotent
Yusker retries deliveries until it receives a 2xx, so the same event can arrive more than once. Key your handler on event.id(or the transfer id) and make the side-effect a no-op if you've already processed it.

Retries

Non-2xx responses are retried with exponential backoff for up to 24 hours. Return 200 as soon as you've durably enqueued the event.