POST /api/v1/webhook/sync accepts reconciliation events from an issuer platform. It is the only endpoint authenticated with an issuer API key rather than a bearer token, and it requires three headers on every request.
All three headers are mandatory. The endpoint returns 401 unless every one is present and valid — there is no partial mode.

The three headers

Signature

The signed string is the nonce, a literal ., then the exact bytes you send as the body — not a re-serialised copy. Serialise your payload once, sign that string, and send that same string. Re-encoding between signing and sending is the most common cause of a rejected signature. The server compares in constant time.

Nonce

x-nonce is rejected if it is more than five minutes from server time in either direction, and rejected if the same key has already used that value. Every request needs a fresh nonce — including retries. Reusing the nonce from a failed attempt will fail again as a replay.

Key binding

Your key must belong to the issuer named in data.issuer._id, or be unclaimed. The first correctly signed call binds an unclaimed key to that issuer permanently. Send your first request carefully; the binding cannot be undone through the API.
apiSecret is returned only in the response that creates the key. It is not retrievable afterwards — store it when you create it.

Signing a request

Troubleshooting a 401

Almost always a body mismatch. Confirm you signed the exact string you sent — no pretty-printing on one side, no key reordering, no re-serialisation by your HTTP client. In Python, pass data= rather than json=, or the client will re-encode the payload.
Your clock has drifted more than five minutes from ours. Sync against NTP.
You retried with the nonce from the previous attempt. Generate a fresh one for every request, including retries of a failed one.
Either the key is inactive, or it is already bound to a different issuer than the one in data.issuer._id.