"Receivers" to "Customers" migration: final notice and complete guide
The transition period announced in the June 4 changelog has ended, and the final release that makes "customers" the only name across the BlindPay platform is about to roll out. This post is the complete guide to everything that changes.
Timing: the renames below are not live yet. They ship with the final release, which will be announced on this changelog. Until then, the receiver_* request fields remain the accepted shape on the current API (sending customer_* request fields today is rejected). Use this guide, and the AI prompt at the end, to prepare your migration diff now, and deploy it when the release goes live.
Endpoints
Every legacy /receivers path now returns 301 Moved Permanently pointing at its /customers equivalent.
| Was | Now |
|---|---|
/v1/instances/{id}/receivers[/...] | /v1/instances/{id}/customers[/...] |
/v1/e/instances/{id}/receivers[/...] | /v1/e/instances/{id}/customers[/...] |
/v1/instances/{id}/limits/receivers/{id} | /v1/instances/{id}/limits/customers/{id} |
/v1/instances/{id}/external-receiver-token | /v1/instances/{id}/external-customer-token |
This covers the customer collection and item routes plus every sub-resource: bank accounts, wallets, blockchain wallets, virtual accounts, offramp wallets, limits, limit increases, and RFIs. The /e/ external invite-flow variants redirect too.
Note that external-receiver-token is renamed even though it has no /receivers/ path segment.
Webhooks
receiver.new, receiver.update, and receiver.delete no longer fire. Subscribe to customer.new, customer.update, and customer.delete instead; they carry the same payloads. The dual-emit behavior from the transition window is gone, so you now receive exactly one event per action.
Renamed fields
| Was | Now | Where |
|---|---|---|
receiver_id | customer_id | Payins, payouts, quotes, transfers, bank accounts, wallets, blockchain wallets, virtual accounts, offramp wallets, limit increases, RFIs, TOS. Also the path segment and list filter. |
receiver_name | customer_name | Customer list filter query parameter |
receiver_local_amount | customer_local_amount | Quotes, payouts |
receiver_wallet_address | customer_wallet_address | Transfers, transfer quotes |
receiver_network | customer_network | Transfers, transfer quotes |
receiver_token | customer_token | Transfers, transfer quotes |
receiver_invite_redirect_url | customer_invite_redirect_url | Instance settings |
receiver_rfi_emails_enabled | customer_rfi_emails_enabled | Instance settings |
receivers_amount | customers_amount | GET /v1/instances, the count of customers on the instance |
receiver_type | customer_type | RFI |
receiver_kyc_status | customer_kyc_status | RFI |
receiver_aiprise_session_id | customer_aiprise_session_id | RFI |
receiver_aiprise_user_profile_id | customer_aiprise_user_profile_id | RFI |
The one field that keeps its name
receiver_amount is not renamed. It stays receiver_amount on quotes, payins, payouts, and transfers, because there it means "the amount the receiving side gets", a leg of the transaction rather than a reference to the customer resource.
Do not confuse it with receivers_amount (plural), which is renamed to customers_amount. That one is the customer count on an instance.
This is the single reason a blind find-and-replace of receiver to customer will break your integration.
Renamed error codes
The code field on error responses is a stable identifier meant for programmatic handling, and eleven of them changed prefix.
| Was | Now |
|---|---|
RECEIVERS_NOT_FOUND | CUSTOMERS_NOT_FOUND |
RECEIVERS_ALREADY_APPROVED | CUSTOMERS_ALREADY_APPROVED |
RECEIVERS_KYC_NOT_APPROVED | CUSTOMERS_KYC_NOT_APPROVED |
RECEIVERS_ONBOARDING_INCOMPLETE | CUSTOMERS_ONBOARDING_INCOMPLETE |
RECEIVERS_INVALID_DATA | CUSTOMERS_INVALID_DATA |
RECEIVERS_INVALID_PHONE | CUSTOMERS_INVALID_PHONE |
RECEIVERS_INVALID_TAX_ID | CUSTOMERS_INVALID_TAX_ID |
RECEIVERS_ID_DOCUMENT_INVALID | CUSTOMERS_ID_DOCUMENT_INVALID |
RECEIVERS_COUNTRY_NOT_SUPPORTED | CUSTOMERS_COUNTRY_NOT_SUPPORTED |
RECEIVERS_ENHANCED_KYC_REQUIRED | CUSTOMERS_ENHANCED_KYC_REQUIRED |
RECEIVERS_BUSINESS_ENHANCED_NOT_AVAILABLE | CUSTOMERS_BUSINESS_ENHANCED_NOT_AVAILABLE |
Renamed error messages
The legacy message slug also changed on the errors below. If you branch on message rather than code, update both.
| Was | Now |
|---|---|
receiver_not_found | customer_not_found |
receiver_id_not_found | customer_id_not_found |
receiver_already_approved | customer_already_approved |
receiver_kyc_not_approved | customer_kyc_not_approved |
receiver_not_approved | customer_not_approved |
receiver_limit_not_found | customer_limit_not_found |
receiver_already_has_limit_increase_in_review | customer_already_has_limit_increase_in_review |
vm_invalid_receiver_data | vm_invalid_customer_data |
vm_receiver_country_not_supported | vm_customer_country_not_supported |
vm_unsupported_receiver_type | vm_unsupported_customer_type |
beneficiary_name_must_match_receiver_for_first_party | beneficiary_name_must_match_customer_for_first_party |
blockchain_wallet_does_not_belong_to_receiver | blockchain_wallet_does_not_belong_to_customer |
sender_and_receiver_networks_must_be_the_same | sender_and_customer_networks_must_be_the_same |
sender_and_receiver_tokens_must_be_the_same | sender_and_customer_tokens_must_be_the_same |
Two message slugs are deliberately unchanged, because they describe the receiving leg of a transaction rather than the customer resource: otc_only_supported_for_sender_without_cover_fees_and_receiver_with_cover_fees, and every slug involving receiver_amount. The currency_type request enum also keeps its sender and receiver values.
Deprecation headers are gone
/receivers responses no longer carry Deprecation: true, Sunset, or Link: rel="successor-version". If you set up the CI smoke test suggested in the June changelog, it now passes trivially instead of catching anything. Replace it with a check that asserts no 301 responses from BlindPay.
IDs are unchanged
Customer IDs keep the re_ prefix, and customer records keep both id and its canonical alias customer_id. No data migration is needed. Do not rewrite stored IDs.
Migrate your code with an AI agent
If you use an AI coding agent (Claude Code, Codex, Cursor, Windsurf, or similar), paste the prompt below into it from the root of your integration. It contains every rename from this changelog and the June announcement, including the exceptions that make a naive find-and-replace unsafe.
What you need to do
- Update API paths from
/receiversto/customers, including the/e/invite-flow variants andexternal-customer-token. - Rename request and response fields per the table above, leaving
receiver_amountalone. - Update error handling:
codecomparisons fromRECEIVERS_*toCUSTOMERS_*, andmessagecomparisons fromreceiver_*tocustomer_*. - Subscribe to
customer.*webhooks in the dashboard and update your handlers. - Update your SDK to the latest release of its current major, then switch
receivers.*calls tocustomers.*. - Leave stored IDs untouched. The
re_prefix is permanent.
If you completed the migration before July 3, 2026, the only new work is step 3, the error code and message renames, which ship with this release.
Verification checklist
- Logs show zero
301responses fromapi.blindpay.com, since each one is an unmigrated path - Logs show zero requests to
/v1/instances/*/receivers*and/v1/e/instances/*/receivers* - No code path reads
response.receiver_idor any other renamed field receiver_amountis still read correctly on quotes, payins, payouts, and transfers- No code path compares an error
codeagainst aRECEIVERS_*value, or an errormessageagainst areceiver_*slug - Requests still send
currency_type: 'receiver', not'customer' - Webhook handlers process
customer.new,customer.update, andcustomer.delete, and the dashboard subscription lists them - SDK updated, with no remaining
receivers.*accessor calls - Saved dashboard URLs use
/customers/
FAQ
What breaks if I do nothing?
Requests keep working through the 301 redirects, at the cost of an extra round-trip per call, as long as your HTTP client follows redirects (browsers, curl, requests, axios, the official SDKs, and Postman all do by default). Three things break outright: receiver.* webhook subscriptions go silent, code that reads a renamed receiver_* response field gets undefined, and error handling that branches on a RECEIVERS_* code or a receiver_* message stops matching.
Do I need to migrate my stored IDs?
No. All IDs keep the re_ prefix, and both id and customer_id carry the same value. We renamed the API surface, not the underlying resource.
Why does receiver_amount keep its name?
Because it does not refer to the customer resource. On a quote or a payment it means the amount landing on the receiving side, the counterpart to sender_amount. Renaming it to customer_amount would have made it read like a property of the customer record.
Will a find-and-replace work?
Not safely. receiver_amount must survive untouched while receivers_amount must change, and stored re_ IDs must not be rewritten. Use the agent prompt above, which encodes those exceptions, or do the renames field by field.
How do I report issues with the migration?
Use the feedback button in the dashboard (under your profile dropdown) or email support@blindpay.com with migration in the subject. Including the request ID from the response (x-blindpay-request-id header) speeds up the lookup.