Go Back

"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.

WasNow
/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

WasNowWhere
receiver_idcustomer_idPayins, payouts, quotes, transfers, bank accounts, wallets, blockchain wallets, virtual accounts, offramp wallets, limit increases, RFIs, TOS. Also the path segment and list filter.
receiver_namecustomer_nameCustomer list filter query parameter
receiver_local_amountcustomer_local_amountQuotes, payouts
receiver_wallet_addresscustomer_wallet_addressTransfers, transfer quotes
receiver_networkcustomer_networkTransfers, transfer quotes
receiver_tokencustomer_tokenTransfers, transfer quotes
receiver_invite_redirect_urlcustomer_invite_redirect_urlInstance settings
receiver_rfi_emails_enabledcustomer_rfi_emails_enabledInstance settings
receivers_amountcustomers_amountGET /v1/instances, the count of customers on the instance
receiver_typecustomer_typeRFI
receiver_kyc_statuscustomer_kyc_statusRFI
receiver_aiprise_session_idcustomer_aiprise_session_idRFI
receiver_aiprise_user_profile_idcustomer_aiprise_user_profile_idRFI

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.

WasNow
RECEIVERS_NOT_FOUNDCUSTOMERS_NOT_FOUND
RECEIVERS_ALREADY_APPROVEDCUSTOMERS_ALREADY_APPROVED
RECEIVERS_KYC_NOT_APPROVEDCUSTOMERS_KYC_NOT_APPROVED
RECEIVERS_ONBOARDING_INCOMPLETECUSTOMERS_ONBOARDING_INCOMPLETE
RECEIVERS_INVALID_DATACUSTOMERS_INVALID_DATA
RECEIVERS_INVALID_PHONECUSTOMERS_INVALID_PHONE
RECEIVERS_INVALID_TAX_IDCUSTOMERS_INVALID_TAX_ID
RECEIVERS_ID_DOCUMENT_INVALIDCUSTOMERS_ID_DOCUMENT_INVALID
RECEIVERS_COUNTRY_NOT_SUPPORTEDCUSTOMERS_COUNTRY_NOT_SUPPORTED
RECEIVERS_ENHANCED_KYC_REQUIREDCUSTOMERS_ENHANCED_KYC_REQUIRED
RECEIVERS_BUSINESS_ENHANCED_NOT_AVAILABLECUSTOMERS_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.

WasNow
receiver_not_foundcustomer_not_found
receiver_id_not_foundcustomer_id_not_found
receiver_already_approvedcustomer_already_approved
receiver_kyc_not_approvedcustomer_kyc_not_approved
receiver_not_approvedcustomer_not_approved
receiver_limit_not_foundcustomer_limit_not_found
receiver_already_has_limit_increase_in_reviewcustomer_already_has_limit_increase_in_review
vm_invalid_receiver_datavm_invalid_customer_data
vm_receiver_country_not_supportedvm_customer_country_not_supported
vm_unsupported_receiver_typevm_unsupported_customer_type
zenus_business_va_requires_business_receiverzenus_business_va_requires_business_customer
beneficiary_name_must_match_receiver_for_first_partybeneficiary_name_must_match_customer_for_first_party
blockchain_wallet_does_not_belong_to_receiverblockchain_wallet_does_not_belong_to_customer
sender_and_receiver_networks_must_be_the_samesender_and_customer_networks_must_be_the_same
sender_and_receiver_tokens_must_be_the_samesender_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.

text

What you need to do

  1. Update API paths from /receivers to /customers, including the /e/ invite-flow variants and external-customer-token.
  2. Rename request and response fields per the table above, leaving receiver_amount alone.
  3. Update error handling: code comparisons from RECEIVERS_* to CUSTOMERS_*, and message comparisons from receiver_* to customer_*.
  4. Subscribe to customer.* webhooks in the dashboard and update your handlers.
  5. Update your SDK to the latest release of its current major, then switch receivers.* calls to customers.*.
  6. 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 301 responses from api.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_id or any other renamed field
  • receiver_amount is still read correctly on quotes, payins, payouts, and transfers
  • No code path compares an error code against a RECEIVERS_* value, or an error message against a receiver_* slug
  • Requests still send currency_type: 'receiver', not 'customer'
  • Webhook handlers process customer.new, customer.update, and customer.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.