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

# B2B API Overview

> Learn the authentication, response, scope, identifier, and retry rules for the B2B API.

The B2B API is the primary REST API for external integrators. You can define
strategies, enroll users, monitor portfolios, and withdraw assets.

Give the [LLMs.txt](https://api.glider.fi/v2/llms.txt) file to your preferred
AI model. You can then ask questions about the API.

## Mental model

A **strategy** is a reusable template. It contains an allocation, a schedule,
and swap preferences. A **portfolio** connects one user to a strategy. It has
one smart account for each chain.

All enrolled portfolios use the allocation and schedule of the strategy. A
new strategy version changes their target for the next rebalance.

There are two rebalance triggers:

* **Scheduled**: Uses the strategy `frequency`. Read `nextDueAt` and
  `lastRebalanceAt` from the portfolio `schedule`.
* **Manual**: `POST /v2/portfolios/{id}/rebalance` starts one rebalance outside
  the schedule. A short cooldown applies to each portfolio.

## Asset coverage

Strategy allocations and portfolio positions accept each supported CAIP-19
asset. Supported assets include ERC-20 tokens, SPL tokens, and tokenized
real-world assets.

`GET /v2/portfolios/{id}/positions` uses one row format for all asset types.

## Chain abstraction

The Glider wallet infrastructure routes cross-chain deposits. It also moves
assets between supported chains when required. Your client does not need to
plan these migrations.

## Machine-readable specifications

Use these files for coding agents and SDK generators. These files are the
source of truth for the API.

| Artifact                  | URL                                     | Purpose                                           |
| ------------------------- | --------------------------------------- | ------------------------------------------------- |
| OpenAPI 3.1 JSON          | `https://api.glider.fi/v2/openapi.json` | Generate SDKs, typed clients, Postman collections |
| LLM-friendly markdown     | `https://api.glider.fi/v2/llms.txt`     | Primer for coding agents (Claude, Cursor, etc.)   |
| Interactive docs (Scalar) | `https://api.glider.fi/v2/docs`         | Try-it-out UI with live request builder           |

## Base URL

```
https://api.glider.fi/v2
```

Use `https://staging-api.glider.fi/v2` for integration tests. Contact
`developers@glider.fi` for a staging API key.

## Authentication

Each business route except `GET /v2/scopes` requires an API key. Send the key
in the `x-api-key` header. The OpenAPI file, interactive reference, and
LLM-friendly reference are public.

HTTP header names are not case-sensitive. The B2B API documentation uses
lowercase for `x-api-key`.

```bash theme={null}
curl -H "x-api-key: gldr_sk_your_api_key" https://api.glider.fi/v2/whoami
```

`GET /v2/whoami` returns the tenant identity and the assigned scopes. Call
this route first to test the key.

## Response envelope

The B2B API uses one response envelope. **Tracing identifiers are in the
response headers, not in the JSON body.**

### Success

```json theme={null}
{
  "success": true,
  "data": { /* endpoint-specific */ }
}
```

### Paginated success

```json theme={null}
{
  "success": true,
  "data": { /* endpoint-specific */ },
  "nextCursor": "eyJjIjoi..." // null on the last page
}
```

`nextCursor` is next to `data`. It is not inside `data`. Each collection in
`data` has a named key, such as `data.portfolios`.

### Error

```json theme={null}
{
  "success": false,
  "error": {
    "code": "API_400",
    "message": "Request validation failed",
    "details": ["allocation.assets: Allocation weights must sum to 100"]
  }
}
```

The `details` field is optional. The API omits it when `message` contains all
applicable information.

### Tracing headers

Each response includes these headers:

| Header             | Purpose                                                   |
| ------------------ | --------------------------------------------------------- |
| `X-Correlation-Id` | Cross-service trace id. Quote this when reporting issues. |
| `X-Request-Id`     | Unique per request.                                       |

The B2B API does not put `correlationId`, `requestId`, or `timestamp` in the
body. Read these values from the headers.

## Scopes

Each authenticated route requires one scope. If the key does not have this
scope, the API returns `403 API_104`.

| Scope                 | Tier     | Grants                                                                    |
| --------------------- | -------- | ------------------------------------------------------------------------- |
| `strategies:read`     | default  | List and view strategies                                                  |
| `strategies:write`    | standard | Create strategies and publish versions                                    |
| `portfolios:read`     | default  | List and view user portfolios, poll operations                            |
| `portfolios:write`    | standard | Pause, resume, trigger rebalances, and update portfolio metadata          |
| `portfolios:withdraw` | standard | Prepare and submit user-signed withdrawal authorizations                  |
| `enroll:write`        | standard | Enroll new users into a strategy (creates smart accounts and a portfolio) |
| `tenant:read`         | standard | Read tenant-wide execution and schedule defaults                          |
| `tenant:write`        | standard | Update tenant-wide execution and schedule defaults                        |
| `fees:read`           | standard | Read tenant and per-strategy swap-fee configuration                       |
| `fees:write`          | standard | Update tenant and per-strategy swap-fee configuration                     |

Tiers:

* **default**: Assigned to each new key.
* **standard**: Assigned to an integrator on request. Contact
  `developers@glider.fi` to upgrade.
* **restricted**: Requires a commercial agreement.

Call `GET /v2/scopes` to read the current scope list. This route does not
require authentication. Call `GET /v2/whoami` to read the scopes for your key.

## Identifiers (CAIP)

All onchain identifiers use
[CAIP](https://github.com/ChainAgnostic/CAIPs). Thus, the same request format
works for each supported chain. Do not send bare hex addresses.

| Identifier                             | Form                                                                                                            | When to use                                                                                                                                                              |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| End-user wallet (EVM EOA)              | **Chain-agnostic** CAIP-10: `eip155:0:0x<addr>`                                                                 | Owner addresses in EVM enrollment and portfolio reads. The same EOA works on every EIP-155 chain, so the chain reference is `0` per CAIP-10 §Abstract Account Addresses. |
| End-user wallet (Solana)               | CAIP-10: `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:<base58>`                                                     | Owner address for Solana-rooted (Model B) enrollment. Solana has no chain-agnostic `0` form, so the mainnet CAIP-2 reference is used.                                    |
| Smart account / smart-contract account | **Chain-bound** CAIP-10: `eip155:<chainId>:0x<addr>` (EVM) or `solana:<ref>:<base58>` (Solana Swig sub-account) | Smart accounts, session-key agents, withdrawal recipients. The account exists only at that (chain, address) tuple.                                                       |
| Asset (ERC-20)                         | CAIP-19: `eip155:<chainId>/erc20:0x<addr>`                                                                      | Strategy allocations, withdrawal assets.                                                                                                                                 |
| Asset (SPL, Solana)                    | CAIP-19: `solana:<ref>/spl:<mint>`                                                                              | Same surface, Solana-native assets.                                                                                                                                      |

Withdrawal recipients must be chain-bound. The recipient chain must match
each asset chain. One withdrawal can use only one chain.

The recipient can be any address that the owner authorizes. This rule applies
to EVM and Solana. The API rejects a transfer to the source smart account.

See [CAIP identifiers](/guides/caip-identifiers) for a worked walk-through.

## Supported Chains

Each deployment has a configured set of enrollment chains. An EVM chain
requires a nonempty `JSON_RPC_URL_<chainId>` value. Solana (`1399811149`)
requires `SOLANA_RPC_URL` and the applicable tenant entitlement.

Do not use a fixed global chain list. Ask Glider which chains are enabled in
the applicable environment. An unsupported chain returns `400 API_400`. The
`error.details` field identifies the rejected `chainIds`.

You select portfolio chains during enrollment. An EVM portfolio can add
chains later with the two-stage
[chain-activation flow](/api-reference/endpoints/v2-activate-chains-signature)
(`POST /v2/portfolios/{portfolioId}/chains/signature` +
`POST /v2/portfolios/{portfolioId}/chains`).

### Solana (SVM) enrollment

The `svm_b2b_api` entitlement controls Solana enrollment for each tenant.
Contact `developers@glider.fi` to enable it. Without it, a Solana enrollment
request returns `403 API_104`.

Each enrollment request uses one namespace. Send Solana (`1399811149`) chain
IDs or EVM chain IDs. Do not send both. Both owner models create a Swig smart
wallet. Its sub-account is the deposit address.

* **Solana-rooted (Model B)**: `ownerAccountId` is a `solana:` CAIP-10, and
  the user signs a Solana transaction returned by stage 1.
* **EVM-rooted (Model A)**: `ownerAccountId` stays `eip155:0:<addr>` with
  `chainIds: [1399811149]`. The secp256k1 key of the user becomes the Swig root and
  authorizes the sub-account with a slot-bound signature.

See [Two-stage enrollment](/guides/two-stage-enrollment#solana-svm-enrollment)
for the request and response formats. Solana withdrawals use the same owner
models. Stage 1 returns `data.authorization` instead of `data.typedData`.
Stage 2 accepts a hex or base58 signature. See
[Prepare Withdrawal Authorization → Solana withdrawals](/api-reference/endpoints/v2-withdraw-signature#solana-withdrawals).

## Monetary Values

The API sends monetary values as decimal strings. This format prevents IEEE
754 precision loss.

| Field                        | Format                                             | Example                        |
| ---------------------------- | -------------------------------------------------- | ------------------------------ |
| `totalValueUsd`, `valueUsd`  | 6 decimal places                                   | `"1500.500000"`                |
| `balance`                    | Full precision, trailing zeros trimmed             | `"14562044.3028598485"`        |
| `balanceRaw`, `amountRaw`    | Integer string, no decimal, no scientific notation | `"14562044302859848500000000"` |
| `priceUsd`                   | 6 decimal places                                   | `"1.000000"`                   |
| Strategy allocation `weight` | Percent with up to 2 decimal places                | `"60"` or `"33.33"`            |
| Exposure `weight`            | Fraction from 0 to 1                               | `"0.6"` or `"0.3333"`          |
| `decimals`                   | Integer (the only numeric financial field)         | `6`                            |

For a full withdrawal, read `balanceRaw` from
`GET /v2/portfolios/{portfolioId}/positions`. Send this value as `amountRaw`.
Do not calculate it from `balance`.

## Pagination

Pagination uses a cursor based on `(createdAt, id)`.

* `limit`: Minimum 1, maximum 200, and default 50.
* `cursor`: An opaque base64url string.
* `nextCursor`: `null` when there are no more pages.

Do not decode or create cursors. Glider owns the cursor format and can change
it. Send the previous `nextCursor` unchanged.

## Idempotency

Write routes with permanent effects use an idempotency anchor. An identical
replay returns the original response. A replay with a different body returns
`409 API_008`.

| Route                               | Anchor          | Sourced from                                           |
| ----------------------------------- | --------------- | ------------------------------------------------------ |
| `POST /v2/enroll`                   | `flowId`        | `POST /v2/enroll/signature` response                   |
| `POST /v2/portfolios/{id}/withdraw` | `message.nonce` | `POST /v2/portfolios/{id}/withdraw/signature` response |

See [Idempotency](/guides/idempotency) for retry rules and the three 409
sub-codes you may see.

## Asynchronous operations

Write routes that start onchain work return `202` and an `operationId`. Poll
the operation every 2–5 seconds. Stop when the state is `completed`, `failed`,
or `cancelled`.

## Error codes

All B2B API error codes use the `API_XXX` format. The number range identifies
the category. The following table contains common codes.

| Code      | HTTP | Meaning                                                                                  |
| --------- | ---- | ---------------------------------------------------------------------------------------- |
| `API_006` | 404  | Resource not found                                                                       |
| `API_007` | 409  | Idempotency replay in progress — retry after a short wait                                |
| `API_008` | 409  | Idempotency key conflict — same anchor, different body                                   |
| `API_101` | 401  | `x-api-key` header missing                                                               |
| `API_102` | 401  | API key invalid                                                                          |
| `API_104` | 403  | Missing required scope, or Solana enrollment not enabled for your tenant (`svm_b2b_api`) |
| `API_200` | 404  | Portfolio not found or not owned by tenant                                               |
| `API_202` | 409  | Portfolio already exists for this `(strategyId, ownerAccountId)`                         |
| `API_210` | 400  | Insufficient balance for withdrawal                                                      |
| `API_211` | 400  | Invalid recipient                                                                        |
| `API_212` | 400  | Duplicate `assetId` in withdrawal                                                        |
| `API_213` | 400  | Withdrawal chain mismatch (recipient vs asset chain)                                     |
| `API_214` | 400  | Withdrawal `message.portfolioId` mismatches the path param                               |
| `API_215` | 400  | Portfolio has no smart account on the recipient's chain                                  |
| `API_216` | 400  | Withdrawal authorization expired (past `message.expiresAt`)                              |
| `API_217` | 400  | Withdrawal signature does not recover to the portfolio owner                             |
| `API_400` | 400  | Request validation failed — see `details[]`                                              |
| `API_506` | 503  | Signature verifier temporarily unavailable — safe to retry                               |
| `API_600` | 500  | Internal server error                                                                    |

For the full list, see [Error codes](/guides/error-codes).

## Tracing and support

Include the `X-Correlation-Id` header when you report an issue. Glider uses
this value to find related logs.

## Next steps

* [Glider's Security Architecture](/guides/security-architecture)
* [Two-stage enrollment](/guides/two-stage-enrollment)
* [Two-stage withdrawal](/guides/two-stage-withdrawal)
* [Idempotency](/guides/idempotency)
* [CAIP identifiers](/guides/caip-identifiers)
