For the complete documentation index, see llms.txt. This page is also available as Markdown.

Webhooks

Swapper sends a signed, server-to-server webhook when a deposit completes. Use it as your reliable source of truth for crediting accounts — unlike a widget event, a webhook isn't lost when the user closes the tab, and it's retried on failure.

Setup

Webhook delivery is configured on Swapper's side. Swapper registers your endpoint URL against your integratorId and issues a signing secret. To set or change your endpoint, or to receive your secret, contact Support.

Your endpoint must be:

  • served over HTTPS;

  • publicly reachable from the internet;

  • fast — return HTTP 2xx within 10 seconds (slow responses count as a failure and trigger a retry).

app.post("/webhooks/deposit", (req, res) => {
  const { eventId, eventType, data } = req.body;
  const { deposit } = data;
  console.log("Deposit completed:", deposit.id, deposit.txHash);
  res.json({ received: true });
});

The event

transaction.completed is the only event type. You are notified once, when a deposit completes — there are no created / processing / failed events.

Top-level fields

Field
Type
Description

eventId

string

Unique event id — use for idempotency.

eventType

string

Always transaction.completed.

timestamp

string

ISO 8601 timestamp of the event.

data.deposit

Deposit

The deposit (below).

data.integratorId

string

Your integrator id.

Deposit object

Field
Type
Description

id

string

Unique deposit id.

method

string

onramp | smart_wallet | dex_swap.

status

string

Lifecycle status — completed on this event.

destinationAddress

string

Where funds are delivered (see Linking).

integratorId

string

Your integrator id.

source

Asset

What went into the swap.

deposited

Asset?

What the user originally deposited (smart_wallet).

destination

Asset?

What was delivered on the destination chain.

depositTxHash

string?

onramp only — the on-chain tx that delivered crypto into the smart wallet.

fundingTxs

string[]?

smart_wallet only — every on-chain tx that funded the swap.

txHash

string?

Source-chain swap tx hash.

destinationTxHash

string?

Destination-chain tx hash (cross-chain).

createdAt

string

ISO 8601.

updatedAt

string

ISO 8601.

completedAt

string?

ISO 8601.

providerData

ProviderData

Method-specific data (below).

Asset

Field
Type
Description

chainId

string

Chain identifier.

tokenAddress

string

Token contract address.

tokenSymbol

string?

Token symbol, when known.

amount

string?

Amount in the token's smallest unit.

amountUsd

string?

USD value, when known.

ProviderData

Discriminated by type:

Example — smart-wallet swap

Verifying the signature

Every request includes an X-Webhook-Signature header: an HMAC-SHA256 signature of the raw JSON request body, keyed with your integrator secret, Base64-encoded. Verify it before trusting a payload.

Algorithm

HMAC-SHA256

Encoding

Base64

Header

X-Webhook-Signature

Payload

Raw JSON string of the request body

Delivery, retries & idempotency

  • Attempts: each event is delivered up to twice — an initial attempt, then one retry about 30 seconds later if the first doesn't succeed.

  • Per-attempt timeout: 10 seconds. A slow response is treated as a failure.

  • Success = HTTP 2xx. Any non-2xx (or a timeout) triggers the retry; after the second failure we stop, and the event is not redelivered later.

  • Idempotency: a retry redelivers the same event, so deduplicate on eventId and make your handler idempotent. Return 200 quickly, then process asynchronously.

Linking onramp ↔ wallet deposit

Advanced — only relevant if you support fiat on-ramps that are swapped onward using smart wallets.

When a fiat on-ramp funds one of our smart wallets and we swap those funds onward, you receive two independent deposits — one onramp and one smart_wallet — each as its own transaction.completed event. They are correlated on-chain, by the tx that delivered crypto into the smart wallet:

  • the onramp deposit carries that delivery tx as depositTxHash;

  • the smart_wallet deposit carries fundingTxs — every tx that funded the swap.

A smart_wallet deposit belongs to an onramp deposit when its fundingTxs contains the onramp's depositTxHash:

Event order is not guaranteed — the swap often completes before the on-ramp settles — so buffer an unmatched deposit (keyed by the funding tx) until its partner arrives.

Things to know

  • Don't double-count volume. The two deposits represent the same money (fiat → token). Count the flow once, keyed by the funding tx.

  • onramp completion depends on destination. A standalone on-ramp (delivered straight to an external wallet) is fully done at completed. If it funds a smart wallet, final delivery is the linked smart_wallet deposit's event (which may arrive later).

  • destinationAddress differs by design: the on-ramp deposit targets the smart wallet (intermediate); the smart_wallet deposit targets the user's final wallet.

  • Field presence: fundingTxs is only on smart_wallet deposits; depositTxHash is on onramp deposits and absent on plain dex_swap.

  • Compare hashes case-insensitively.

Support

If something looks wrong, open a ticket in Discord with your integratorId, an example eventId, the relevant deposit.id and funding tx hash (depositTxHash or a fundingTxs entry), recent log entries, and your endpoint URL. See Support.

Last updated