Quickstart
Create an endpoint, watch a wallet and receive your first webhook.
You need a server reachable over HTTPS (port 443 or 8443) that can receive a POST, and curl.
1. Get an API key
- Create an account in the dashboard and confirm your email with the code we send you.
- Open API keys and click Create key. For this guide, tick all three permissions.
- Copy the key. It starts with
whk_test_and is shown once.
Then set two variables so the commands below can be pasted as they are:
export API=https://api.webhookdev.xyz
export KEY=whk_test_...Authentication covers permissions, expiry, IP limits and rolling a key.
The examples from here on come in three flavours. The Node.js ones use the built-in fetch
(Node 18 or newer); the Python ones use requests. Both read
the same two environment variables, API and KEY.
2. Create an endpoint
curl -X POST $API/v1/endpoints \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"url":"https://example.com/webhooks/stellar","description":"production"}'The response contains the endpoint's id and its secret (whsec_...). The secret is also shown
only once. Your server uses it to verify signatures.
3. Check that your server receives webhooks
curl -X POST $API/v1/endpoints/ENDPOINT_ID/test -H "Authorization: Bearer $KEY"This sends a test.ping event and returns the result of the first attempt:
{ "eventId": "evt_01K...", "attempt": { "statusCode": 200, "durationMs": 84, "error": null } }4. Watch a wallet
curl -X POST $API/v1/watches \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{
"walletAddress": "G...",
"label": "Shop checkout",
"endpointId": "ENDPOINT_ID",
"assets": [{ "code": "USDC", "issuer": "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5" }],
"amountRule": { "kind": "min", "amount": "10" },
"memoRule": { "kind": "present" }
}'The response includes warnings. ACCOUNT_NOT_FOUND or NO_TRUSTLINE:USDC mean the wallet cannot
receive that asset yet; the watch is still saved, so you can fix the wallet afterwards.
walletAddress is the public address, starting with G. If you paste a secret key (S...) the
request is refused. Never send a secret key to any service.
Rules you can set
| Field | Options |
|---|---|
assets | One or more of { "code": "XLM", "issuer": null } or { "code": "...", "issuer": "G..." }. |
amountRule | { "kind": "any" }, exact, min or max with amount, or range with min and max. Amounts are decimal strings; edges are inclusive. |
memoRule | { "kind": "any" }, present, absent, or equals with value and type (text, id or hash). |
senderAllowlist | Addresses allowed to pay. Empty means anyone. |
eventTypes | payment.received (default). Add payment.rejected to be told about payments that fail the rules. |
5. Send a payment
Pay the wallet on testnet with at least 10 USDC and any memo. See the testnet guide for funding an account and sending a payment. Within seconds your server receives:
{
"id": "evt_01K6V8Z3M4T7Q2X9B5N1R0C8YD",
"type": "payment.received",
"apiVersion": "2026-10-01",
"createdAt": "2026-10-03T20:41:22.512Z",
"data": {
"payment": {
"id": "0021506181151346688-0000000000",
"txHash": "afe052cee2d66dae5ba90e3010655a8e4ebcc5fe1db3352aa42e45036e6240d4",
"ledger": 5007298,
"ledgerClosedAt": "2026-10-03T20:41:17.000Z",
"from": "GDXT3JQDWX7IXTYCSFPK4RANVX2EJDTQ57L2IZWSYBLDZIUPAFJCQAUF",
"to": "GBFMHWFQFQV3ZGGTWFFBGJQJPTRX3UBT7ZWBMUELVHJIUBSFDP5HQD56",
"toMuxedId": null,
"memo": "order-1001",
"memoType": "text",
"asset": { "code": "USDC", "issuer": "GBBD47IF6LWK7P7MDEVSCWR7DPUWV3NY3DTQEVFL4NAT4AQH3ZLLFLA5" },
"amount": "10.0000000",
"amountStroops": "100000000"
},
"watch": { "id": "cm...", "label": "Shop checkout", "walletAddress": "GBFM..." },
"verification": { "outcome": "VERIFIED", "reasons": [] }
}
}Answer with any 2xx status within 10 seconds. Do the real work after you have answered.
What to do in your handler
- Verify the signature using the raw request body.
- Check whether you have already processed this
Webhook-Id. If so, answer200and stop. See retries and duplicates. - Record the event, answer
200, then process it.