Skip to main content
An external reference ID is your own identifier for a Fluz user. It lets you operate the Fluz API using the IDs you already have in your system — without storing or passing Fluz’s internal userId and accountId for every user. When a user authorizes your application, you attach your identifier to that grant. Fluz stores the pairing between your identifier and the user’s Fluz account, scoped to your application. From that point forward you can reference the user by your own ID when generating tokens, sending transfers, and matching webhook events. The practical payoff: you never have to build a Fluz-ID lookup table. A webhook arrives, it carries your user ID, you route it. No join, no cache, no reconciliation job.

One value, three field names

The same value appears under a different name depending on the surface. This is the most common source of confusion on this page, so it’s worth memorizing before you start. Because it’s embedded in the access token, the association survives token refreshes — you assign it once, at grant time, and it persists.

Choosing an identifier

Never use PII. No email addresses, phone numbers, or names.Two reasons, both concrete. First, they change — people switch emails and phone numbers, and your mapping breaks permanently because the value is immutable once set. Second, this value travels in query strings and JWT claims, which means it lands in browser history, referrer headers, proxy logs, and your own application logs. Don’t put personal data there.
The most expensive mistake is scoping it to the wrong thing. An external reference ID identifies a person, permanently — not a transaction, a payout run, a session, or an order. If you pass a per-transaction identifier, the first transfer succeeds and the second one creates a second mapping to the same human, and you’ve forked one user into many with no way to merge them.If you find yourself generating a new value for each operation, you want an idempotency key, not an external reference ID.

The rules


Assigning one

Standard OAuth applications

Append external_id to the authorization URL when you send the user to consent (see Client-facing OAuth grant flow):
When the user completes the grant, Fluz records usr_8f3d2a91 against that user’s authorization of your application. Optional here, but strongly recommended. Adopting it later means backfilling grants one re-authorization at a time.

Widget applications

Required. All widget application types — deposit, payout, pay-in, virtual card, gift card catalog, bill pay, and external payout — require an external reference ID to establish a user session. Without one the request is rejected:
For widgets, the value travels as the externalId claim inside the signed pre-approved transaction token, alongside the amount and transaction type. You generate it server-side; it is not a client-side init option. See Set Up Your Server.
externalId and jti sit next to each other in the same token and answer different questions. externalId is who — stable for the life of the user. jti is which transaction — new every time. Reusing jti breaks idempotency; changing externalId forks your user.

Using one

Address transfer destinations

When creating a wallet transfer to another Fluz account (see Transfer to Another Fluz Wallet), identify the destination by your own ID instead of a Fluz account ID:
Provide either destination.accountId or destination.externalReferenceId — never both. The destination user must have authorized your application, or the transfer is rejected.

Match webhook events to your users

Webhook payloads carry externalReferenceId, so you can route events without a lookup table:
Handle the field being absent. externalReferenceId is omitted where the user’s grant has no external reference ID associated, or where the event is flagged as private. A handler that assumes the field is always present will throw on those deliveries — and a webhook handler that throws is a webhook you didn’t process.
See Configure App Widget for webhook setup.

Getting user-scoped tokens

generateUserAccessToken does not accept an externalReferenceId — it identifies the user by userId and accountId (see Generate a User Access Token). For users you reference by your own ID, use the OAuth flow instead. The grant already carries your identifier, and the tokens you get by exchanging the authorization code at /token/exchange are issued for that user with the association embedded. See Exchange an OAuth Authorization Code.

End to end

One user, one identifier, four surfaces.
1

Your system already knows this person

User usr_8f3d2a91 in your database clicks Connect Fluz.
2

Assign at consent

You redirect to /authorize with external_id=usr_8f3d2a91. They sign in, verify if needed, and approve your scopes. Fluz binds usr_8f3d2a91 to their account, for your application only.
3

Exchange

Your callback exchanges the code for an accessToken and refreshToken. The association is embedded, so it survives every future refresh. You store the tokens against usr_8f3d2a91 — no Fluz UUIDs in your schema.
4

Operate

You pay them out with destination: { externalReferenceId: "usr_8f3d2a91" }, using your own ID as the address.
5

Reconcile

The completion webhook arrives carrying externalReferenceId: "usr_8f3d2a91". You route it straight to that user’s record and mark the payout settled. No join, no lookup, no cache.

Lifecycle

Backfilling an existing grant

If a user authorized your application before you adopted external reference IDs, supply one on a subsequent authorization and Fluz backfills it onto the existing grant — provided the grant doesn’t already carry one. An existing value is never overwritten.

Re-authorizing with a different value

Because an existing value is never overwritten, passing a different external_id for a user who already has one does not change the mapping. Plan on the first value being permanent. If your user IDs are unstable, mint a dedicated immutable ID for Fluz rather than reusing something you might migrate.

Deleting users on your side

Never recycle an identifier. If you hard-delete a user and later reissue the same primary key to a different person, that new person inherits the old mapping — and the old person’s Fluz account. Use UUIDs, or a monotonic sequence you never reset.

Validation rules and errors

Troubleshooting


What an external reference ID is not

  • Not a Fluz userId or accountId. Those are Fluz-issued UUIDs; this one is issued by you.
  • Not an idempotency key. That’s idempotencyKey on API calls and jti in widget tokens, and it’s unique per operation. This is unique per person.
  • Not the state parameter in the OAuth flow. state is per-authorization-attempt CSRF protection and is not stored.
  • Not the external account identifiers that appear on withdrawal records or linked funding sources. Those reference banking and processor records, not users.

Next steps

Grant flow

Where you assign the identifier for OAuth apps.

Set up your server

Where you assign it for widget apps.

Transfer to another Fluz wallet

Addressing transfers by your own ID.

Configure app webhooks

Receiving events that carry it back.