> For the complete documentation index, see [llms.txt](https://docs.zebec.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zebec.io/developer-docs/partner-api/topup-flow.md).

# Top-up flow

The top-up flow lets a partner add funds to a user's Carbon card using crypto held in the user's wallet.

## Flow overview

1. **Discover programs** — `GET /partner/v1/topup/programs`
2. **Build a quote** — `GET /partner/v1/topup/quote`
3. **User signs and sends the on-chain transfer** using the quote's payment instructions.
4. **Preflight checks** — `POST /partner/v1/topup/preflight`
5. **Submit the top-up** — `POST /partner/v1/topup`
6. **Poll status** — `GET /partner/v1/topup/{orderId}`

## 1. Discover programs

```http
GET /partner/v1/topup/programs
Authorization: Bearer <accessToken>
```

Returns available Carbon programs, currencies, accepted tokens, and each token's `sourceTokenMint`.

## 2. Build a quote

```http
GET /partner/v1/topup/quote?amount=...&sourceChain=...
Authorization: Bearer <accessToken>
```

The backend prices the top-up and returns:

* `id` — use this as `quoteId` in later requests.
* Payment instructions, including chain and `contractAddress`.
* A resolved `cardId`.
* A canonical signing message the end user must sign with their wallet.

Quotes are valid for **2 minutes**. The `expiresIn` field is an absolute expiration timestamp in Unix milliseconds.

## 3. On-chain transfer

The user submits the on-chain token transfer using the chain and `contractAddress` returned in the quote's `payment` object. Keep the on-chain receipt (including `txHash`).

## 4. Preflight

```http
POST /partner/v1/topup/preflight
Authorization: Bearer <accessToken>
{
  "quoteId": "..."
}
```

Validates KYC, balance, and the buyer wallet against the live quote. The result is cached by `quoteId`.

## 5. Submit

```http
POST /partner/v1/topup
Authorization: Bearer <accessToken>
{
  "quoteId": "...",
  "receipt": { "deposit": { "txHash": "..." } },
  "userSignature": "..."
}
```

The backend verifies the signature against the buyer wallet, consumes the quote, and enqueues the order through the validator → OnBe pipeline.

Submit idempotency is keyed by the on-chain `receipt.deposit.txHash` for **7 days**.

## 6. Poll status

```http
GET /partner/v1/topup/{orderId}
Authorization: Bearer <accessToken>
```

Poll until the order reaches a terminal state.

## Required scope

Top-up endpoints require the `cards:topup` scope.

For full request/response schemas, see the [Swagger UI](https://dev-super.api.zebec.io/api/partner).
