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

# Bulk API

> Read and act across many connected Fluz users in a single call, instead of looping over one user token at a time.

The Bulk API lets your application act across **many connected Fluz users in a single call** — instead of looping over one user token at a time. It's built for OAuth application developers who need to read or (soon) move funds on behalf of the users who have connected to your app.

<Note>
  This is different from the "Create Virtual Card Bulk Order" operation under Virtual Cards, which creates many cards for a *single* account. The Bulk API operates *across your connected users*.
</Note>

## Who can use it

The Bulk API is gated at the application level. Your app must have the **bulk API capability** enabled by Fluz — reach out to us to request access. Calls that aren't from a bulk-enabled application are rejected with `BulkApiAccessDenied`.

## Authentication

All Bulk API calls use **Basic authentication with your application API key** (your `client_id` and `client_secret`), not a user access token:

```
Authorization: Basic <API_KEY>
```

Endpoint (staging):

```
https://transactional-graph.staging.fluzapp.com/api/v1/graphql
```

Endpoint (production):

```
https://transactional-graph.fluzapp.com/api/v1/graphql
```

## Authorization comes from existing connections

The Bulk API never creates a new consent surface. A user is only reachable if they have an **active OAuth grant** with your application, and each operation is allowed only where the user has granted the scopes that operation requires. Bulk access is never broader than the equivalent single-user operation.

* Disconnecting removes the grant, so a disconnected user simply stops being reachable.
* If a user's grant is scoped to specific spend accounts, bulk results for that user are automatically restricted to those accounts.

## Selecting target users

Every bulk operation takes a `targetSpec`:

| Mode            | Meaning                                                            |
| --------------- | ------------------------------------------------------------------ |
| `ALL_CONNECTED` | Every user currently connected to your application.                |
| `SELECTED`      | Only the users whose `externalReferenceId`s you list in `targets`. |

* Users are addressed by the `externalReferenceId` you supplied when they connected — not by `accountId`.
* A synchronous request addresses at most **100 targets**.
* Users connected without an `externalReferenceId` can't be selected individually; they're only reachable via `ALL_CONNECTED`. Use [Discover Connected Users](/discover-connected-users) to see who's connected and which scopes they granted.

## Per-target failure contract

One target's failure **never fails the whole request**. Each result carries `success` and, when `success` is `false`, an `error`:

| Code                        | Meaning                                                                                     |
| --------------------------- | ------------------------------------------------------------------------------------------- |
| `TARGET_NOT_CONNECTED`      | The id isn't a user currently connected to your app (unknown, revoked, or never connected). |
| `INVALID_TARGET_IDENTIFIER` | The id isn't a valid identifier.                                                            |
| `INSUFFICIENT_SCOPE`        | The user hasn't granted the scopes this operation requires.                                 |
| `ACCOUNT_NOT_PERMITTED`     | The user's grant doesn't permit this operation on the requested account.                    |

The whole request is only rejected for application-level problems: not bulk-enabled, an invalid request, exceeding the 100-target cap, or when *every* requested target is unresolvable.

Each response also summarizes `targetCount`, `successCount`, and `failureCount`.

## Synchronous vs. asynchronous

* **Bounded reads are synchronous** and served inline: up to 100 targets, with per-target limits (e.g. 20 transactions each, a 90-day window). These are the three queries documented in this section.
* **Writes and large exports are asynchronous** (coming soon): you submit a job, poll its status, and download results. `hasNextPage`/`totalCount` on the sync reads tell you when to switch to an export rather than silently truncating.

## Operations in this section

* [Discover Connected Users](/discover-connected-users) — `getBulkConnectedOAuthUsers`
* [Get Bulk Balances](/get-bulk-balances) — `getBulkBalances`
* [Get Bulk Transactions](/get-bulk-transactions) — `getBulkTransactions`
