Webhooks
Webhooks let your backend update orders when Bitcoin payment state changes. Manatee sends events to the webhook_url you provide when creating a payment.
Event types
| Event type | Meaning | Typical action |
|---|---|---|
payment.detected | A matching transaction was seen, but confirmations are below the required threshold. | Show "payment seen" or "waiting for confirmations". |
payment.confirmed | The transaction reached required_confirmations. | Mark the order as paid or ready for fulfillment. |
Treat payment.detected as an early signal. Use payment.confirmed as the fulfillment trigger for most production flows.
Payload example
{
"version": "1",
"type": "payment.confirmed",
"data": {
"payment_id": "pay_abc123",
"txid": "a1b2c3d4...",
"address": "tb1q...",
"amount_sats": 10000,
"received_sats": 10000,
"confirmations": 1,
"webhook_url": "https://yourapp.example/webhooks/btc"
}
}
Store the payment ID returned during payment creation next to your own order ID. Webhook payloads contain the Manatee payment ID and transaction data; your backend should use the stored mapping to find the order.
Required headers
| Header | Purpose |
|---|---|
X-Manatee-Event-Id | Unique event delivery ID for replay protection and idempotency. |
X-Manatee-Event-Type | Event type, such as payment.detected or payment.confirmed. |
X-Manatee-Timestamp | Unix timestamp in seconds used in signature verification. |
X-Manatee-Signature | HMAC-SHA256 signature over timestamp + "." + raw request body. |
Always verify X-Manatee-Signature before updating an order, and reject timestamps outside your allowed clock-skew window. See Security for implementation details.
For backwards compatibility, Manatee currently also sends the legacy X-Event-ID, X-Event-Type, and X-Signature headers. New integrations should use the X-Manatee-* headers.
Send a test webhook
Before creating a payment, you can send a synthetic payment.confirmed event to your webhook endpoint:
curl -X POST "$MANATEE_API_URL/v1/webhooks/test" \
-H "Authorization: Bearer $MANATEE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://yourapp.example/webhooks/btc"
}'
This checks endpoint reachability, payload parsing, signature handling, and response behavior without sending a Bitcoin transaction. It does not create a payment and is not stored in payment history.
Webhook failed
If webhook delivery fails:
- Confirm the URL is publicly reachable by server-to-server HTTP requests.
- Return a
2xxresponse only after your app accepts the event. - Bypass browser challenges, captchas, or login redirects only for the webhook route.
- Verify the raw request body, not parsed JSON, when checking signatures.
- Store
X-Manatee-Event-Idvalues so repeated delivery is safe.
For retry behavior and more details, see Webhook Delivery in a Bitcoin Payment API.