Skip to main content

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 typeMeaningTypical action
payment.detectedA matching transaction was seen, but confirmations are below the required threshold.Show "payment seen" or "waiting for confirmations".
payment.confirmedThe 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

HeaderPurpose
X-Manatee-Event-IdUnique event delivery ID for replay protection and idempotency.
X-Manatee-Event-TypeEvent type, such as payment.detected or payment.confirmed.
X-Manatee-TimestampUnix timestamp in seconds used in signature verification.
X-Manatee-SignatureHMAC-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 2xx response 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-Id values so repeated delivery is safe.

For retry behavior and more details, see Webhook Delivery in a Bitcoin Payment API.