> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fluz.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Managing External Reference IDs

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.

> 📘 **Where you'll see it**
>
> The field appears as `external_id` in the OAuth authorization URL and as `externalReferenceId` in the GraphQL API and webhook payloads. They are the same value.

## What can it be?

| Property   | Rule                                                                                                                                                                           |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Type       | Any string. Fluz does not impose a format.                                                                                                                                     |
| Uniqueness | Must be unique per user **within your application**. One external reference ID maps to exactly one Fluz user.                                                                  |
| Scope      | Scoped to your OAuth client. The same Fluz user can carry a different external reference ID in another developer's application, and no other application can see or use yours. |
| Stability  | Treat it as immutable. Use a stable identifier from your system — your internal user ID or a UUID.                                                                             |

> ⚠️ **Do not use PII as an external reference ID**
>
> Avoid email addresses, phone numbers, or names. These can change over time and would break your mapping, and they unnecessarily transmit personal data in URLs and tokens. A UUID or your database primary key is the right choice.

## Where do we use it?

The external reference ID flows through four surfaces:

| Surface                             | Field                             | Direction  |
| ----------------------------------- | --------------------------------- | ---------- |
| OAuth authorization URL             | `external_id` query parameter     | You → Fluz |
| `generateUserAccessToken` mutation  | `externalReferenceId` argument    | You → Fluz |
| Wallet transfers (`createTransfer`) | `destination.externalReferenceId` | You → Fluz |
| Webhook event payloads              | `externalReferenceId`             | Fluz → You |

It is also embedded in the OAuth access token issued for the user, so the association persists across token refreshes.

## How do we use it?

### 1. Assign it during the OAuth authorization flow

When you direct your end user to the authorization URL (see [Client facing OAuth grant flow](/client-facing-o-auth-grant-flow)), append your identifier as the `external_id` query parameter:

```text theme={null}
https://uni.staging.fluzapp.com/authorize?response_type=code&client_id=<CLIENT_ID>&redirect_uri=<REDIRECT_URI>&scopes=MAKE_DEPOSIT%20LIST_PAYMENT&external_id=usr_8f3d2a91
```

When the user completes the grant, Fluz records `usr_8f3d2a91` against that user's authorization of your application. The same parameter applies when launching an embedded widget — see [Widget Overview](/developers/widgets).

> 🚧 **Required for widget applications**
>
> All widget application types (deposit, payouts, payins, virtual card, gift card catalog, bill pay, and external payout widgets) **require** an external reference ID when establishing a user session. The request will be rejected with `External reference ID is required for <type> applications` if it is omitted. For standard OAuth applications it is optional, but strongly recommended.

### 2. Generate user access tokens with it

Once the pairing exists, `generateUserAccessToken` accepts `externalReferenceId` in place of `userId` and `accountId`:

```graphql theme={null}
mutation {
  generateUserAccessToken(
    externalReferenceId: "usr_8f3d2a91"
    scopes: [MAKE_DEPOSIT, LIST_PAYMENT]
  ) {
    token
    refreshToken
    scopes
  }
}
```

Authenticate this call with your application's Basic credentials as usual — see [Generate a User Access Token](/recipes/generate-user-access-token).

You may pass `userId`/`accountId` alongside `externalReferenceId`, but they must match the user the external reference ID resolves to. If they don't, the request is rejected.

### 3. Address transfer destinations with it

When creating a wallet transfer to another Fluz account (see [Transfer to Another Fluz Account](/features/transfer-to-another-fluz-wallet)), the destination can be identified by external reference ID instead of a Fluz account ID:

```graphql theme={null}
mutation {
  createTransfer(input: {
    idempotencyKey: "1f7c5a2e-9b14-4c6d-8e3f-2a90d4b7c1aa"
    amount: 25.00
    destination: { externalReferenceId: "usr_8f3d2a91" }
  }) {
    transferId
  }
}
```

Provide either `destination.accountId` or `destination.externalReferenceId` — never both. The destination user must have authorized your application; otherwise the transfer is rejected.

### 4. Match webhook events back to your users

Webhook payloads include `externalReferenceId` so you can correlate Fluz events to your own user records without maintaining a lookup table of Fluz IDs:

```json theme={null}
{
  "userId": "5070d5a1-d71a-4190-91b0-f116eec51771",
  "accountId": "9c2e1b44-7a3d-4f08-b6e5-d18a3c7f0e22",
  "externalReferenceId": "usr_8f3d2a91",
  "eventType": "DEPOSIT_COMPLETE",
  "amount": 100.00
}
```

See [Configure App Widget](/developers/configure-app-widget) for webhook setup and delivery details.

> 📘 **Privacy note**
>
> `externalReferenceId` is omitted from webhook payloads where the user's grant has no external reference ID associated, or where the event is flagged as private.

## Validation rules and errors

| Scenario                                                                                 | Result                                                                                   |
| ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| Token request with neither `externalReferenceId` nor `userId` + `accountId`              | `Provide either externalReferenceId or both userId and accountId.`                       |
| `externalReferenceId` not found for your application                                     | `No user found with externalReferenceId <value>.`                                        |
| `userId` provided alongside `externalReferenceId` but pointing to a different user       | `Provided userId does not match the user associated with the externalReferenceId.`       |
| `accountId` provided alongside `externalReferenceId` but pointing to a different account | `Provided accountId does not match the account associated with the externalReferenceId.` |
| Transfer destination with both `accountId` and `externalReferenceId`                     | `Provide either destination.accountId or destination.externalReferenceId, not both.`     |
| Transfer destination user has not authorized your application                            | `Destination account has not authorized this application.`                               |
| Widget session created without an external reference ID                                  | `External reference ID is required for <type> applications`                              |

## Adding an external reference ID to an existing grant

If a user authorized your application before you adopted external reference IDs, you can supply one on a subsequent authorization or token request and Fluz will backfill it onto the existing grant — provided the grant does not already carry one. An existing external reference ID is never overwritten.

## What an external reference ID is not

* It is **not** a Fluz `userId` or `accountId`. Those are Fluz-issued UUIDs; the external reference ID is issued by you.
* It is **not** the `external_id` or external account identifiers that appear on withdrawal records or linked funding sources elsewhere in the API. Those reference banking and processor records, not users. \[TBD: confirm whether any of these are exposed in the public schema and should be cross-referenced here]

<StickyContactSalesBanner />

<br />
