Merchant webhook authentication remains Morphosis callback HMAC v1. It is intentionally separate from request HMAC v2.

Receive payment.updated

The payment.updated event tells a merchant that a payment state changed. The event is a notification: verify its signature, deduplicate it, validate the payload, and apply the transition idempotently. Verify. Deduplicate. Validate. Apply. Acknowledge.

Endpoint configuration

Register an HTTPS webhook URL with Morphosis when your sandbox merchant profile is issued. Local development can use a tunnel; Stage Sandbox deliveries target the registered URL only.

Event shape

Signature headers

Build the canonical string by joining the version, event identifier, timestamp, and base64url SHA-256 digest of the raw body with line-feed characters: The reproducible vector below hashes the UTF-8 bytes returned by JSON.stringify(event) for the event above, with no trailing newline. A real receiver must instead hash the exact bytes it received and must not parse and reserialize the body before verification.
Compute an HMAC-SHA256 over that canonical string with the webhook signing secret and encode the result as unpadded base64url.

Processing order

1

Capture the raw body

Preserve the exact bytes received. Parsing and reserializing JSON before verification changes the digest.
2

Verify authenticity

Check the version, key identifier, timestamp, event identifier, and signature. Compare the computed signature in constant time.
3

Reserve the event identifier

Insert event_id into a unique store before applying business effects. If it already exists, return the same successful acknowledgement without repeating fulfilment.
4

Validate and apply

Match payment_id, external_reference, amounts, asset, network, and destination to the local order. Apply only a valid lifecycle transition.
5

Acknowledge

Return an empty 200 response only after the event is safely recorded.
Delivery is at least once. Retries and explicit redelivery preserve the same event_id. After repeated failures the gateway may dead-letter the delivery for operator inspection; merchants should still be able to reconcile with GET /v2/payments/{payment_id}.