1. Webhooks
Public API
  • Get Started
  • Payments
    • Create payment
      POST
    • List payments
      GET
    • Get payment by ID
      GET
  • Webhooks
    • Integration Guide
    • Webhook Definitions
      • Payment Created
      • Payment Completed
      • Payment Expired
  1. Webhooks

Integration Guide

Webhooks#

Woldy uses webhooks to notify your server about events — for example, when a payment is successfully completed or has expired. You need to create an HTTP endpoint that Woldy will send POST requests to.

Quick Start#

1.
Create an HTTPS endpoint to receive webhook requests
2.
Register a webhook in the dashboard under Settings → Webhooks
3.
Save the Public Key shown in the dashboard — you will need it to verify signatures
4.
Verify the signature of every incoming request
5.
Return HTTP 2xx in response to each request

Setup#

Webhook creation and management is available through the dashboard under Settings → Webhooks.
When creating a webhook, specify:
URL — your server's HTTPS endpoint (HTTP is not supported)
Events — the event types to subscribe to
Description — optional
After creation, you will be shown the Public Key (Ed25519, base64). Save it — it is displayed only once.
Limits: max 10 webhooks per branch, HTTPS only, private IPs and localhost are not allowed.

Incoming Request#

Each webhook is a POST request with Content-Type: application/json.

Headers#

HeaderValue
X-Woldy-SignatureEd25519 signature, base64 Standard Encoding (RFC 4648, with = padding)
X-Woldy-Signature-VersionAlways ed25519-v1
X-Woldy-Event-IDEvent UUID — xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
X-Woldy-Event-TypeEvent type, e.g. payment.created
X-Woldy-TimestampUnix timestamp of the request (integer, seconds)
Content-Typeapplication/json
User-AgentWoldy-Webhooks/1.0

Body example#

{
  "id": "wev_VQ6EA4np...",
  "branch_id": "cb_VQ6EA4np...",
  "webhook_id": "wh_VQ6EA4np...",
  "type": "payment.completed",
  "api_version": "2026-01-01",
  "created_at": 1737720000,
  "data": {
    "id": "p_VQ6EA4np...",
    "amount": "100.50",
    "status": "COMPLETED",
    "currency": "USDT"
  }
}
For the full schema of each event type see the Event Definitions.

Signature Verification#

Always verify the signature before processing event data.

How it works#

Woldy signs every request using Ed25519. The signed string is:
{timestamp}.{eventID}.{bodyJSON}
Where:
timestamp — value from X-Woldy-Timestamp
eventID — value from X-Woldy-Event-ID (raw UUID)
bodyJSON — the exact raw bytes of the HTTP request body
The signature covers the entire request body. Always verify against the raw body bytes — never re-serialize parsed JSON.

Steps#

1.
Extract X-Woldy-Timestamp, X-Woldy-Event-ID, X-Woldy-Signature from headers
2.
Check freshness: |now - timestamp| ≤ 300 seconds
3.
Build: "{timestamp}.{eventID}.{bodyJSON}"
4.
Decode X-Woldy-Signature from base64 Standard Encoding
5.
Verify Ed25519 signature with the Public Key from the dashboard
Node.js
Python
Go

Retry Policy#

If your server returns an error (4xx, 5xx) or does not respond within 10 seconds:
AttemptDelay
1Immediately
2~1 minute
3~5 minutes
4~30 minutes
5~2 hours
After 5 failed attempts the delivery is marked FAILED.

Best Practices#

Respond quickly — return 200 immediately, process asynchronously.
Handle duplicates — the same event may arrive more than once. Use uid for deduplication.
Always verify — never process a webhook without verifying the signature.

Troubleshooting#

Not receiving events — check webhook status in the dashboard (ACTIVE?), confirm you subscribed to the correct event type.
Signature error:
Use the Public Key from the dashboard (shown once at creation)
Sign only the data field, not the full body
Do not re-sort keys — serialize data exactly as received (no whitespace, key order from the body)
X-Woldy-Event-ID is a raw UUID, not wev_...
Timestamp must be within ±5 minutes
Decode signature from base64 Standard Encoding (with = padding)
Public Key is raw 32-byte Ed25519, not X.509/SPKI
Timeout — respond 200 immediately, process asynchronously.
Modified at 2026-03-18 07:51:55
Previous
Get payment by ID
Next
Payment Created
Built with