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

# Bring Your Own Integration for Plaid (BYOI Plaid)

> Use your own Plaid client ID and secret for the bank links that your users make through your application.

Bring Your Own Integration for Plaid (BYOI Plaid) lets your application use its own Plaid account for bank linking. When BYOI Plaid is on, Fluz uses your Plaid client ID and secret for the bank links that your users make through your application.

<Info>
  BYOI Plaid is a setting for the full application. It applies to all users of your application. Your users do not need a new permission, and you do not change your bank linking code.
</Info>

## Terms on this page

| Term              | Meaning                                                                                                          |
| ----------------- | ---------------------------------------------------------------------------------------------------------------- |
| Developer         | The Fluz user who owns the application in the developer dashboard.                                               |
| Plaid integration | Your Plaid client ID and secret, registered with Fluz for one application in one environment.                    |
| Bank link         | One Plaid connection to one bank login (a Plaid Item). Fluz identifies each bank link with its `platformItemId`. |
| Fluz Plaid        | The Plaid credentials of Fluz. Fluz uses them when BYOI Plaid is off.                                            |

## How BYOI Plaid works

1. You add the `BYOI_PLAID` permission to your application.
2. The developer registers your Plaid client ID and secret with `registerPlaidIntegration`.
3. Fluz sends a test request to Plaid to validate the credentials. Then Fluz stores them in an encrypted vault.
4. BYOI Plaid starts immediately for all users of your application.
5. Each new bank link that a user makes through your application uses your Plaid credentials.

You continue to use the same operations: `createPlaidLinkToken`, `completePlaidLink`, and the other operations in [Linking Bank Account via Plaid](/features/link-via-plaid).

### Which credentials each bank link uses

Each bank link always uses the Plaid credentials that created it.

| Bank link                                                                                            | Credentials that Fluz uses          | Available to your application                                        |
| ---------------------------------------------------------------------------------------------------- | ----------------------------------- | -------------------------------------------------------------------- |
| New bank link made through your application while BYOI Plaid is on                                   | Your Plaid credentials              | Yes                                                                  |
| Bank link made with Fluz Plaid, for example before you turned on BYOI Plaid                          | Fluz Plaid                          | Yes                                                                  |
| Bank link made with the Plaid integration of a different application                                 | The credentials of that application | No                                                                   |
| Bank link made with an earlier Plaid integration of your application that used a different client ID | The earlier credentials             | No. See [Change your Plaid client ID](#change-your-plaid-client-id). |

Fluz can also use the bank links that your credentials created. For example, Fluz checks the balance of these bank accounts. For these requests, Fluz uses your Plaid credentials.

## Before you start

| Requirement      | Details                                                                                                                                                                                                                      |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Fluz application | An enabled application. Only the developer of the application can register, read, or disable its Plaid integration.                                                                                                          |
| Plaid account    | API access in the Plaid environment that matches the Fluz environment. See the table below.                                                                                                                                  |
| Plaid products   | Auth, Transactions, Identity, Signal, and Balance must be available for your client ID. Fluz requests Auth, Transactions, Identity, and Signal when it creates a Link token. Fluz uses Balance for real-time balance checks. |
| Country          | United States. Fluz creates Link tokens for US banks only.                                                                                                                                                                   |
| User permissions | Your users need `MANAGE_PAYMENT`, the same as for all bank linking. Your users do not need `BYOI_PLAID`.                                                                                                                     |

### Environments

Each Fluz environment uses one Plaid environment. Register your credentials in each Fluz environment separately. A registration in one environment does not apply to the other environment.

| Fluz environment | GraphQL URL                                                      | Plaid environment | Secret to register           |
| ---------------- | ---------------------------------------------------------------- | ----------------- | ---------------------------- |
| Staging          | `https://transactional-graph.staging.fluzapp.com/api/v1/graphql` | Sandbox           | Your Plaid Sandbox secret    |
| Live             | `https://transactional-graph.fluzapp.com/api/v1/graphql`         | Production        | Your Plaid Production secret |

## Step 1: Add the BYOI\_PLAID permission to your application

1. In the developer dashboard, open **Your apps**.
2. Select your application.
3. Open the permissions tab that matches the Fluz account of the developer:
   * For a consumer account, open the **Permissions** tab.
   * For a business account, open the **Business permissions** tab.
4. Select **Link bank accounts through your own Plaid integration**. This is the `BYOI_PLAID` permission in the **Update Account Info** group.
5. Save the application.

## Step 2: Get an access token for the developer

The Plaid integration operations need a user access token with these properties:

* The token belongs to the developer of the application.
* The token includes the `BYOI_PLAID` scope.
* The token is a Bearer token. Basic auth is not accepted.

To get this token:

1. Send the developer through the OAuth grant flow. See [Client-Facing OAuth Grant Flow](/client-facing-o-auth-grant-flow).
2. Log in as the developer and approve the requested permissions. The consent screen includes `BYOI_PLAID` because you added it in Step 1.
3. Exchange the authorization code for tokens. See [Exchange an OAuth Code](/exchange-an-o-auth-authorization-code).
4. Make sure that the `scope` list in the token response includes `BYOI_PLAID`.

If the developer authorized your application before you added `BYOI_PLAID`, the old grant does not include it. Do the OAuth grant flow again.

Send the token in each request:

```http theme={null}
Authorization: Bearer <developer-access-token>
```

## Step 3: Register your Plaid credentials

```graphql theme={null}
mutation RegisterPlaidIntegration($input: RegisterPlaidIntegrationInput!) {
  registerPlaidIntegration(input: $input) {
    change
    plaidIntegration {
      plaidIntegrationId
      name
      environment
      status
      validatedAt
    }
  }
}
```

```json theme={null}
{
  "input": {
    "clientId": "<your-plaid-client-id>",
    "secret": "<your-plaid-secret>",
    "name": "Acme Plaid"
  }
}
```

```json theme={null}
{
  "data": {
    "registerPlaidIntegration": {
      "change": "CREATED",
      "plaidIntegration": {
        "plaidIntegrationId": "5f0c3c1e-6a4e-4a7b-9f53-2f1b8d0f4a11",
        "name": "Acme Plaid",
        "environment": "PRODUCTION",
        "status": "ACTIVE",
        "validatedAt": "2026-09-23T19:45:00.000Z"
      }
    }
  }
}
```

### Input fields

| Field      | Required | Description                                                                                                                                                                                                                               |
| ---------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `clientId` | Yes      | Your Plaid client ID. 1 to 255 characters.                                                                                                                                                                                                |
| `secret`   | Yes      | Your Plaid secret for the matching Plaid environment. 1 to 255 characters.                                                                                                                                                                |
| `name`     | No       | A label for the integration. The default is the name of your application. The name must be unique in your Fluz account for this environment, also among disabled integrations. Fluz uses the name only when it creates a new integration. |

### Response fields

| Field                                 | Description                                      |
| ------------------------------------- | ------------------------------------------------ |
| `change`                              | What the request changed. See the next table.    |
| `plaidIntegration.plaidIntegrationId` | The Fluz ID of the Plaid integration.            |
| `plaidIntegration.name`               | The label of the integration.                    |
| `plaidIntegration.environment`        | `SANDBOX` or `PRODUCTION`.                       |
| `plaidIntegration.status`             | `ACTIVE` or `DISABLED`.                          |
| `plaidIntegration.validatedAt`        | The time when Plaid accepted the current secret. |

The API never returns your client ID or your secret.

### Values of `change`

| Value         | Meaning                                                                                                                                            |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREATED`     | Fluz created a new Plaid integration. BYOI Plaid is now on.                                                                                        |
| `UNCHANGED`   | The same client ID and secret are already active. Fluz changed nothing. You can safely send the same request again.                                |
| `UPDATED`     | The client ID is already active and the secret is new. Fluz validated the new secret and saved it.                                                 |
| `REACTIVATED` | A disabled integration with this client ID existed. Fluz turned it on again. If the secret was different, Fluz validated and saved the new secret. |

### Registration rules

* Each application can have one active Plaid integration in each environment.
* Fluz validates the credentials with Plaid before it saves them. If Plaid rejects them, Fluz saves nothing.
* Registration turns on BYOI Plaid for the application. The change starts with the next request of each user.

## Read your Plaid integration

```graphql theme={null}
query GetPlaidIntegration {
  getPlaidIntegration {
    plaidIntegrationId
    name
    environment
    status
    validatedAt
  }
}
```

The query returns the active integration. If no integration is active, it returns the most recently changed integration. If you never registered an integration in this environment, it returns `null`.

## Replace your Plaid secret

Use this procedure when you rotate your Plaid secret. Your existing bank links continue to work.

1. In the Plaid Dashboard, create a new secret for the same client ID.
2. Call `registerPlaidIntegration` with the same `clientId` and the new `secret`.
3. Make sure that `change` is `UPDATED`.
4. In the Plaid Dashboard, delete the old secret.

## Change your Plaid client ID

Fluz does not replace an active client ID with a different client ID. If you try, Fluz returns `PLAID_INTEGRATION_CLIENT_ID_MISMATCH`.

1. Call `disablePlaidIntegration`.
2. Call `registerPlaidIntegration` with the new `clientId` and `secret`.
3. Make sure that `change` is `CREATED`.

<Warning>
  Bank links made with the old client ID stop working when you change the client ID. Your users must link these banks again. The old bank links work again only if you register the old client ID again.
</Warning>

## Disable BYOI Plaid

```graphql theme={null}
mutation DisablePlaidIntegration {
  disablePlaidIntegration {
    change
    plaidIntegration {
      plaidIntegrationId
      status
    }
  }
}
```

If an integration was active, `change` is `DISABLED`. If no integration was active, `change` is `UNCHANGED`.

After you disable BYOI Plaid:

* New bank links use Fluz Plaid.
* Bank links made with your credentials stop working. Fluz cannot get new balances or transactions for them, and the users cannot relink them.
* Fluz does not process Plaid webhooks for bank links made with your credentials.

To turn BYOI Plaid on again, register the same client ID. The `change` value is `REACTIVATED`, and the old bank links work again.

<Warning>
  Disable BYOI Plaid before you remove the `BYOI_PLAID` permission from your application. Removing the permission does not turn off BYOI Plaid. It only prevents new tokens from including `BYOI_PLAID`. Without that scope, you cannot call `disablePlaidIntegration`.
</Warning>

## Link a bank account

When BYOI Plaid is on, the linking flow does not change. Follow [Linking Bank Account via Plaid](/features/link-via-plaid):

1. Call `createPlaidLinkToken` with an empty `input`.
2. Open Plaid Link with the returned `linkToken`.
3. Send the `public_token` from Plaid Link `onSuccess` to `completePlaidLink`.
4. Store the returned `platformItemId`.

Plaid Link shows **Fluz** as the application name. Fluz requests 730 days of transaction history.

<Warning>
  Do not send `deviceOs` when BYOI Plaid is on. With `deviceOs`, Fluz sends Plaid the OAuth redirect settings of the Fluz mobile app. Plaid does not accept these settings for your client ID, so the Link token request fails. Use Plaid Link for web without `deviceOs`.
</Warning>

`completePlaidLink` returns only the bank accounts that your application can use. See the table in [Which credentials each bank link uses](#which-credentials-each-bank-link-uses).

## Relink a disconnected bank link

A bank link can disconnect, for example when a user changes the bank password. Applications with a Plaid integration use two operations to repair a bank link:

* `createPlaidRelinkToken` creates a Plaid update-mode Link token with the credentials that created the bank link.
* `completePlaidRelink` confirms the repair with Plaid and updates the bank data. It does not need a `publicToken`.

These operations work for bank links made with your credentials and for bank links made with Fluz Plaid. They keep the same Plaid access token and the same `platformItemId`.

1. Create the relink token.

   ```graphql theme={null}
   mutation CreatePlaidRelinkToken($input: CreatePlaidRelinkTokenInput!) {
     createPlaidRelinkToken(input: $input) {
       linkToken
       expiration
       requestId
       mode
     }
   }
   ```

   ```json theme={null}
   {
     "input": {
       "platformItemId": "<stored-platform-item-id>"
     }
   }
   ```

2. Open Plaid Link with the returned `linkToken`. The value of `mode` is `RELINK`.

3. When Plaid Link calls `onSuccess`, complete the relink.

   ```graphql theme={null}
   mutation CompletePlaidRelink($input: CompletePlaidRelinkInput!) {
     completePlaidRelink(input: $input) {
       bankInstitutionAuthId
       bankInstitutionName
       platformItemId
       bankAccounts {
         bankInstitutionAuthId
         bankAccountId
         bankName
         lastFour
         type
         subtype
       }
     }
   }
   ```

   ```json theme={null}
   {
     "input": {
       "platformItemId": "<stored-platform-item-id>"
     }
   }
   ```

4. If you get `PLAID_ITEM_STILL_DISCONNECTED`, Plaid has not finished the repair. Wait a short time, then call `completePlaidRelink` again.

If you use the relink flow of [Relinking Bank Accounts](/features/relink-accounts) (`createPlaidLinkToken` and `completePlaidLink` with `platformItemId`), it continues to work. If Plaid rejects the `publicToken` of that flow, Fluz completes the relink through the bank link automatically.

## Webhooks

You do not need a webhook endpoint. When Fluz creates a Link token with your credentials, Fluz sets the Plaid webhook URL to a Fluz URL for your integration. Plaid sends the updates for these bank links to Fluz.

Do not change the webhook URL of these bank links, for example with the Plaid `/item/webhook/update` endpoint. If you change it, Fluz stops receiving updates for the bank link.

## Plaid requests made with your credentials

Fluz sends these Plaid requests with your credentials. Plaid charges your Plaid account for them, as specified in your Plaid contract.

| Plaid endpoint                | When Fluz sends it                                          |
| ----------------------------- | ----------------------------------------------------------- |
| `/institutions/get`           | When you register or replace credentials, to validate them. |
| `/link/token/create`          | When a user starts a new link or a relink.                  |
| `/item/public_token/exchange` | When a user completes a new link.                           |
| `/auth/get`, `/accounts/get`  | When Fluz saves the bank accounts of a bank link.           |
| `/accounts/balance/get`       | When Fluz gets a real-time balance.                         |
| `/transactions/get`           | When Fluz gets transaction history.                         |
| `/item/get`                   | When a user completes a relink.                             |
| `/item/remove`                | When a user removes a bank link.                            |
| `/institutions/get_by_id`     | When Fluz saves the details of a bank.                      |

## Errors

Each GraphQL error has a Fluz error code in `extensions.code`. BYOI Plaid errors also have a specific value in `extensions.reason`.

```json theme={null}
{
  "errors": [
    {
      "message": "Plaid rejected the provided clientId and secret.",
      "extensions": {
        "code": "G-0007",
        "reason": "PLAID_INTEGRATION_INVALID_CREDENTIALS"
      }
    }
  ]
}
```

### Errors from the Plaid integration operations

| `extensions.reason`                         | `extensions.code` | Cause and action                                                                                                  |
| ------------------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------- |
| None                                        | `AUTH-0031`       | The token does not include `BYOI_PLAID`. Do Step 2 again.                                                         |
| `PLAID_INTEGRATION_NOT_APP_DEVELOPER`       | `AUTH-0008`       | The token is not a Bearer token of the developer of this application. Use the token of the developer.             |
| None                                        | `AUTH-0034`       | Fluz cannot find the application of the token.                                                                    |
| `PLAID_INTEGRATION_INVALID_INPUT`           | `G-0007`          | `clientId` or `secret` is missing or longer than 255 characters.                                                  |
| `PLAID_INTEGRATION_INVALID_CREDENTIALS`     | `G-0007`          | Plaid rejected the credentials. Make sure that the secret is for the Plaid environment in the environments table. |
| `PLAID_INTEGRATION_CLIENT_ID_MISMATCH`      | `G-0007`          | A different client ID is active. See [Change your Plaid client ID](#change-your-plaid-client-id).                 |
| `PLAID_INTEGRATION_NAME_TAKEN`              | `G-0007`          | Another integration in your Fluz account uses this name. Send a different `name`.                                 |
| `PLAID_INTEGRATION_OWNER_ACCOUNT_MISSING`   | `G-0007`          | The application has no owner account. Contact Fluz support.                                                       |
| `PLAID_INTEGRATION_CREDENTIALS_UNAVAILABLE` | `G-0010`          | Plaid or the credential vault did not respond. Try again later.                                                   |

### Errors from bank linking operations

| `extensions.reason`                         | `extensions.code` | Cause and action                                                                                                                                                         |
| ------------------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `PLAID_ITEM_NOT_ACCESSIBLE_TO_APPLICATION`  | `AUTH-0008`       | The bank link was made with the credentials of a different Plaid integration. Your application cannot use it. The user can link the bank again through your application. |
| `PLAID_INTEGRATION_UNAVAILABLE`             | `G-0010`          | Fluz could not read your Plaid integration. Try again later.                                                                                                             |
| `PLAID_INTEGRATION_CREDENTIALS_UNAVAILABLE` | `G-0010`          | The credentials that created the bank link are disabled, or the vault did not respond. If you disabled the integration, register it again.                               |
| `PLAID_INTEGRATION_REQUEST_FAILED`          | `G-0010`          | The Plaid request failed. Try again later.                                                                                                                               |
| `PLAID_INTEGRATION_AMBIGUOUS`               | `G-0010`          | The Plaid integration of the application is not configured correctly. Contact Fluz support.                                                                              |
| `PLAID_INTEGRATION_OWNER_MISMATCH`          | `G-0010`          | The Plaid integration of the application is not configured correctly. Contact Fluz support.                                                                              |
| `PLAID_ITEM_STILL_DISCONNECTED`             | `G-0010`          | Plaid has not finished the repair. Wait a short time, then call `completePlaidRelink` again.                                                                             |
| `PLAID_RELINK_ITEM_MISMATCH`                | `G-0010`          | Fluz could not confirm the bank link. Start the relink again.                                                                                                            |
| `PLAID_RELINK_ITEM_CHECK_FAILED`            | `G-0010`          | Fluz could not get the status of the bank link from Plaid. Try again later.                                                                                              |
| `PLAID_RELINK_INVALID_REQUEST`              | `G-0007`          | `platformItemId` is missing or not valid.                                                                                                                                |

If `createPlaidLinkToken` fails after you register, make sure that your client ID has access to Auth, Transactions, Identity, and Signal in the matching Plaid environment. Also make sure that you do not send `deviceOs`.

## Security

* Fluz stores your client ID and secret in an encrypted vault. The API never returns them.
* The API never returns Plaid access tokens, Plaid public tokens, bank account numbers, or routing numbers.
* Only the developer of the application can register, read, or disable its Plaid integration.

## Related pages

* [Linking Bank Account via Plaid](/features/link-via-plaid)
* [Relinking Bank Accounts](/features/relink-accounts)
* [Application Scopes](/fluz-dashboard/application-scopes)
* [Configure OAuth App](/create-an-o-auth-app)
* [Client-Facing OAuth Grant Flow](/client-facing-o-auth-grant-flow)

## API reference

* [`registerPlaidIntegration`](/api-reference/mutations/register-plaid-integration)
* [`getPlaidIntegration`](/api-reference/queries/get-plaid-integration)
* [`disablePlaidIntegration`](/api-reference/mutations/disable-plaid-integration)
* [`createPlaidRelinkToken`](/api-reference/mutations/create-plaid-relink-token)
* [`completePlaidRelink`](/api-reference/mutations/complete-plaid-relink)
