GET /api/v1/orders/{id} in a loop.
Base path:
https://virtualsms.io/api/v1/customer/webhooks. Authenticate with the same
x-api-key header as every other endpoint — including a key minted through the
x402 top-up flow.Event types
Exactly five event types exist. Subscribing to anything else is rejected with400.
balance.low requires a threshold; the other four do not.
Create a webhook
URL rules
The URL is validated on create and on update. It must:- use
https://—http://and every other scheme are rejected - resolve to a public host — loopback, private and link-local hosts are rejected
- be at most 2048 characters
Manage webhooks
GET list returns { "success": true, "webhooks": [...], "count": N }.
DELETE returns { "success": true, "id": "3f2a91c4-8e5b-4d17-9a02-c1b6e7f45d80" }.
PATCH accepts any subset of the updatable fields; sending none returns 400. Manually setting
paused: false also resets the consecutive-failure counter to zero.
Test-fire
400.
Delivery history
{ "success": true, "deliveries": [...], "count": N, "limit": 50, "offset": 0 }. Each
delivery carries id, event_id, event_type, attempt, status, response_status,
response_body, scheduled_for, delivered_at, error_message, created_at and the full
payload that was sent. limit defaults to 100 and is capped at 500.
The envelope we POST
Every event — including the test event — has the same envelope shape:id is a ULID-suffixed event id, unique per event and stable across retries — use it to
deduplicate. The contents of data vary by event type.
Headers
Verifying the signature
Compute the HMAC over the raw request body bytes, before any JSON parsing, and compare in constant time.Retries and auto-pause
- Return any 2xx status to acknowledge. Anything else — including a timeout — is a failure.
- Each request times out after 5 seconds.
- Up to 5 attempts per event. Attempt 1 fires immediately; the gaps after a failed attempt are 1 minute, 5 minutes, 30 minutes, 2 hours. After the fifth failure the delivery is marked a permanent failure and is not retried.
- A successful delivery resets your endpoint’s consecutive-failure counter to zero.
- After 20 consecutive failures the endpoint is auto-paused and stops receiving events.
Un-pause it with
PATCH {"paused": false}, which also clears the counter.