Drawing 1 · Interactive
Change the identity and watch the send stop
Stage 5 of 5 · No way back
There is no key to undo a hash; it can only be compared. Short, guessable inputs can still be matched by hashing guesses.
At Send time:a SHA-256 hash
Last contactsees
Networksees
SHA-256 hash starting e3a63b09
Send timesees
SHA-256 hash starting e3a63b09
Hashes match
Decrypt: no key exists
Can check it
- Meta, comparing hashes at send time
- Your system, matching against its trusted hash
Cannot recover it
- Your system: the hash reveals no key
- Logs and CRM records that store the hash
Step 5 of 5, No way back: There is no key to undo a hash; it can only be compared. Short, guessable inputs can still be matched by hashing guesses.
What is the identity change check?
The identity change check is an opt-in safeguard on the WhatsApp Cloud API that has Meta confirm a customer's cryptographic identity before delivering your message. Every WhatsApp account has an identity key tied to its device; when the customer does something WhatsApp treats as an identity change, typically reinstalling the app or moving the account to a new phone, Meta generates a new identity hash for them. With the check enabled on your business phone number, you keep the hash you last saw and send it back with sensitive messages, and Meta delivers only if it still matches.
Once the setting is on, inbound message webhooks include the customer's hash as identity_key_hash in the contacts array, and status webhooks carry it as recipient_identity_key_hash in each statuses entry. You add the stored value as a top-level recipient_identity_key_hash field in a send request, next to to and type. If it matches the customer's current hash, the message goes out as normal; if not, Meta withholds it and sends a failed status webhook with error code 137000 instead. Sends without the field are delivered unchecked, so the protection covers exactly the messages you attach a hash to.
The point is trust in the recipient, not encryption. A bank, lender or clinic that verified a customer once, through KYC, an OTP or a branch visit, otherwise has no way to know that someone else may now hold that WhatsApp account, for example after SIM swap fraud or a stolen phone. The check is also narrower than a number change: when a customer moves to a new phone number, WhatsApp sends a user_changed_number System Message, whereas an identity change means the same number may now be on a different device, possibly in different hands.
Key takeaways
- The identity change check makes the Cloud API refuse delivery when a customer's WhatsApp identity has changed since you stored their hash.
- Turn it on per business number by POSTing
user_identity_change.enable_identity_key_check: trueto the/settingsendpoint. - Webhooks then carry the customer's
identity_key_hash; send it back asrecipient_identity_key_hashto have Meta compare it. - A mismatch is never delivered: a status webhook reports error 137000, and you re-verify the customer outside WhatsApp.
- Only sends that include the hash are checked, so attach it to every message carrying personal or financial data.
Design intent
Why does the identity change check matter?
WhatsApp now carries loan statements, policy documents, OTPs, payout confirmations and lab reports, and every one of them assumes the reader is the person you verified. The identity change check turns a silent risk, a reinstalled account on someone else's handset, into an explicit, machine-readable failure your systems can act on before personal data leaks. For regulated businesses in India it is also the kind of reasonable security safeguard the DPDP Act expects a data fiduciary to be able to show, and a concrete control auditors can test.
Operating sequence
How does the identity change check work?
Enable the setting on the number
POST
{"user_identity_change": {"enable_identity_key_check": true}}to/{PHONE_NUMBER_ID}/settings; the API answers{"success": true}. The setting is per business phone number, so turn it on for every number that sends sensitive messages.Capture a baseline at verification
When a customer passes your own verification (KYC, net-banking login, branch visit), store the
identity_key_hashfrom their latest webhook as the trusted value, with the date and method. That stored hash means 'the device we verified'.Attach the hash to sensitive sends
Add
recipient_identity_key_hashat the top level of the/messagesrequest for statements, OTPs, account changes and anything with personal data. It works the same for text, media and template sends.Treat 137000 as a security event
A
failedstatus with error 137000 means the identity changed since you stored the hash. Mark WhatsApp as untrusted for that customer in your CRM, stop further sensitive sends and start re-verification on a channel that does not depend on that phone.Re-establish trust, then re-baseline
After the customer passes re-verification, resend the failed message without a hash, as Meta recommends, and store the new hash the delivery status webhook returns as the trusted value.
Implementation
The identity change check in code
# 1. Turn the check on for one business phone numbercurl -X POST "https://graph.facebook.com/v26.0/{PHONE_NUMBER_ID}/settings" \-H "Authorization: Bearer {ACCESS_TOKEN}" \-H "Content-Type: application/json" \-d '{ "user_identity_change": { "enable_identity_key_check": true } }'# → { "success": true }# 2. Send a sensitive message with the hash you trust for this customercurl -X POST "https://graph.facebook.com/v26.0/{PHONE_NUMBER_ID}/messages" \-H "Authorization: Bearer {ACCESS_TOKEN}" \-H "Content-Type: application/json" \-d '{"messaging_product": "whatsapp","recipient_type": "individual","to": "919812345678","recipient_identity_key_hash": "{TRUSTED_IDENTITY_KEY_HASH}","type": "text","text": { "body": "Your October loan statement is ready. Reply STATEMENT to receive the PDF." }}'# Delivered only if the hash still matches. Otherwise: a failed status webhook# with error code 137000, and nothing reaches the phone.
The hash sits at the top level of the send request, beside `to` and `type`.
Specifications
The identity change check: key facts and limits
- Setting
- user_identity_change.enable_identity_key_check on POST /{PHONE_NUMBER_ID}/settings
- Scope
- Per business phone number, opt-in
- Inbound webhook field
- contacts[].identity_key_hash
- Status webhook field
- statuses[].recipient_identity_key_hash
- Send request field
- recipient_identity_key_hash (top level)
- On mismatch
- Not delivered; failed status with error 137000
- Sends without a hash
- Delivered unchecked
- Billing
- Undelivered messages are not billed
Failure modes
Common mistakes with the identity change check
Re-baselining from every webhook
Overwriting the stored hash with whatever the latest inbound message or status carries lets a new device quietly become trusted, which defeats the check. Keep the trusted hash tied to your last successful verification and treat a different hash on an inbound message as a warning.
Checking only some sensitive sends
Messages sent without
recipient_identity_key_hashare delivered unchecked. Route every message that carries personal or financial data through one send function that always attaches the hash.Retrying a 137000
Resending with the same hash fails again, and resending without it delivers to whoever now holds the account. Stop, re-verify the customer, and only then resend without the hash.
Re-verifying on the same phone
An OTP to the same WhatsApp account or SIM proves nothing after a takeover or SIM swap. Use a channel independent of that number: a branch, an authenticated app or web session, or a call-back to a number on file.
Confusing it with a number change
A
user_changed_numbersystem message covers a customer moving to a new phone number; the identity change check covers the same number on what may be a different device. Handle both events.
Example: A stolen phone at a Pune lender
A Pune-based NBFC sends monthly loan statements on WhatsApp with the identity change check on. A borrower's phone is stolen; the thief gets a duplicate SIM and restores the WhatsApp account on a new handset. When the statement job runs, its request carries the hash stored when the borrower last verified, Meta sees a different identity, and instead of a delivered PDF the lender gets a status webhook with error 137000. The job pauses WhatsApp for that account and the collections team calls the alternate number on file. Once the borrower confirms the new phone at a branch, the lender resends the statement without a hash and stores the new value as trusted.
Recommended practice
Best practices for the identity change check
- Turn the check on before you start sending statements or OTPs, so every verified customer has a baseline hash.
- Store the hash with the date and method of the verification that made it trusted; that is your audit trail.
- Log 137000 events as security signals, with personal data masked, and watch for spikes that suggest a fraud wave.
- Remember that most identity changes are honest new phones; word the follow-up as a routine security check, not an accusation.