Troubleshooting: BINDING_REQUIRED / BINDING_MISMATCH on Verify
A “binding” is the association between a verification factor run and the device or token that must prove possession of it. Verify factors — passkey, flashcall, SNA, and the PSD2 SCA dynamic-linking binding on OTP sends — mint their challenge against a specific token, and the check will only pass when that same token is replayed on the verify call. A binding gate refuses the call at the 422 layer; it does not consume an attempt and it is not a transient failure — you fix the pairing, not retry. This page covers the two codes that surface the gate. The OTP-delivery and factor-enforcement gates that sit around them are on the Verify OTP and Verify factor suite pages.What a binding is
A binding is the device/token association a factor run must carry across its full life — enroll → send → check. Each factor has its own canonical binding, and the gate rejects any run that loses it:- Passkey — the enrolled public key for the relying party. The verify
challenge is issued against the enrollment; any other key, origin, or
rpIdmismatches the binding. - Flashcall / SNA — a device-bound network token. The SIM possession proof is anchored at send time, and /check must come back through the same device token.
- PSD2 SCA dynamic-linking — the
sca_bindingobject (amount,payee, optionaltransaction_id) you pass onPOST /api/v1/verify/send. The send stores its hash;POST /api/v1/verify/checkmust replay the exact same object or it refuses.
BINDING_REQUIRED — a binding the route needs was not supplied
BINDING_REQUIRED fires when a binding-bearing route is called without
its binding. The two shapes:
A legacy row — one minted before the binding gate existed, or one you sent
without a binding — carries no stored hash and passes
/check unchanged.
The gate only arms when the send itself carried the binding.
Sample envelope:
BINDING_MISMATCH — the replayed token does not match the stored one
BINDING_MISMATCH fires when a binding is supplied but does not match the
one the verification was minted with. The common cause is a token that
drifted between the send and the check: a regenerated device token, a
different rpId or origin on the passkey ceremony, or a replayed
sca_binding whose amount, payee, or transaction_id differs from
what the send stored — even when the numeric value looks the same, a
reformatted amount (10.5 vs 10.50) or a re-cased payee still hashes
differently.
The fix is the same in both cases: pass the stable token. For PSD2 SCA,
store the exact sca_binding your server sent and replay it verbatim —
never recompute it from a parsed copy, because the parse can normalize
whitespace or key order and change the hash. For device tokens, reuse the
same device identifier between factor runs; rotating the device id at
the check stage trips the mismatch. For a passkey, keep the relying party
(rpId, origin) identical between enrollment and verification.
Sample envelope:
Deterministic — do not retry without fixing the pairing
The binding gates are taxonomy-side honour codes. Fix the pairing once and the check passes; retry the same body and the gate keeps refusing. If you are deliberately not on the PSD2 SCA flow, omitsca_binding from
/verify/send and the gate does not arm — but once a send carries one,
every check against that row must carry it too.
See also
- Verify OTP — the send and check gates around the binding codes.
- Verify factor suite — the TOTP, push, passkey, and backup-code factors the binding belongs to.
- Verify API reference — the full request shape for
sca_bindinganddevice_token. - Error codes reference — the platform-wide enum where
BINDING_REQUIREDandBINDING_MISMATCHlive.