Webhooks
Pulse calls your endpoints when an order reaches a milestone.
Pulse sends a POST request to each active endpoint when an order reaches a
milestone. The same events serve orders that you create and orders from
collection deposits. A delivery retry can send the same event more
than once.
Set up webhook endpoints
Open Webhooks in the Dashboard
and select the test or live environment. You can register up to three public
HTTPS endpoints in each environment. Test endpoints receive environment: "test"
events. Live endpoints receive environment: "live" events.
Pulse generates a unique signing secret for each endpoint. The Dashboard shows the secret after endpoint creation or rotation. Store each secret before you close the dialog. Configure each handler with the secret for its endpoint.
Select an endpoint to inspect its delivery attempts or replay a delivery. You can also enable, disable, rotate, or delete the endpoint. Disabled endpoints count toward the three-endpoint limit. Deleting an endpoint frees one endpoint slot.
The previous secret stops working immediately after rotation. Replace it when the Dashboard shows the new secret.
Handle endpoint verification
When you add an endpoint, Pulse sends a verification request to your URL and saves
the endpoint only after it returns a 2xx response. The request can use POST or
GET, and its body can be empty. It carries no X-Pulse-Signature header, because
Pulse generates the signing secret after verification.
Check for X-Pulse-Signature before you read the body. If the header is absent,
return 200 and take no other action. Pulse signs every event delivery.
Event structure
Every event uses the same top-level structure. The data object depends on the
event type.
{
"id": "0198e2f1-3b7c-7a41-9e05-1c8d2f60b933",
"type": "order.payment_received",
"environment": "test",
"created_at": "2026-07-28T10:04:52Z",
"data": {
"order_id": "0198e2d0-…",
"reference": "partner-order-88213"
}
}data.reference is your order reference. For an order from a collection payment,
it is the collection reference.
Events from the test environment carry environment: "test". Events from the live
environment carry environment: "live". Check this field before you process the
event.
The event type identifies the event. Event payloads do not contain a separate
status field.
Event sequence
The events an order sends depend on its source. Deliveries can arrive out of order.
order.failed instead. The event carries a reason.Each order produces one terminal event: completed, expired, or failed.
See Events for each payload, and Testing to trigger each event.
Verify deliveries
Verify each delivery before you process its event. Pulse sets X-Pulse-Signature
to the lowercase hexadecimal HMAC-SHA256 digest of the raw request body. Use the
endpoint signing secret as the HMAC key.
Use the raw request body
Verify the signature before you decode the JSON. Decoding and re-encoding the body can change its bytes and invalidate the signature.
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
)
func verifyPulseSignature(rawBody []byte, signature, secret string) bool {
if signature == "" || secret == "" {
return false
}
providedDigest, err := hex.DecodeString(signature)
if err != nil || len(providedDigest) != sha256.Size {
return false
}
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(rawBody)
expectedDigest := mac.Sum(nil)
return hmac.Equal(providedDigest, expectedDigest)
}hmac.Equal compares the digests in constant time. Reject an invalid signature with
a non-2xx response.
Handle deliveries
Return a 2xx response promptly
Verify and record the event, then return a 2xx response. Complete longer work
after the response. A timeout can cause another delivery of the same event.
Delivery retries
Pulse retries a failed delivery for up to 8 hours with an exponential backoff. A timeout or non-2xx response starts the retries. You can inspect and replay a delivery in the Dashboard.
Duplicate events
Pulse reuses the top-level event ID (id) for every delivery attempt. Record each
processed event ID, and skip a duplicate.
Delivery order
Do not depend on delivery order. Record each event that arrives, even when an earlier event has not arrived yet.