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

# Auto-conversion credentials

> Accept deposits in one currency and settle them into a wallet in a different currency, automatically.

Wallet credentials can accept deposits in a currency that differs from the wallet's own — every arriving deposit is automatically converted into the wallet's currency at the FX rate live at deposit time. Two directions:

* **Auto-onramp** — a fiat credential on a crypto wallet. The payer sends fiat; the wallet is credited in crypto.
* **Auto-offramp** — a crypto credential on a fiat wallet. The payer sends crypto; the wallet is credited in fiat.

Same-currency credentials — where the credential currency matches the wallet's currency — remain the default and credit the wallet balance directly, with no conversion.

## Create a cross-currency credential

Pass an explicit `currency` on [`POST /v1/wallets/:id/credentials`](/api-reference/openapi#tag/wallets/POST/v1/wallets/\{id}/credentials) that is different from the wallet's currency. Currency codes are uppercase (`NGN`, `USDC`, `GHS`, `USDT`, `KES`, …).

<CodeGroup>
  ```bash Auto-onramp (NGN on USDC wallet) theme={null}
  curl https://api.globalstack.io/v1/wallets/wal_01HXYZABC1234567890ABCDEFG/credentials \
    -H "Authorization: Bearer YOUR_SECRET_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "network": "bank",
      "currency": "NGN"
    }'
  ```

  ```bash Auto-offramp (USDC on NGN wallet) theme={null}
  curl https://api.globalstack.io/v1/wallets/wal_01HXYZDEF9876543210ZYXWVUT/credentials \
    -H "Authorization: Bearer YOUR_SECRET_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "network": "base",
      "currency": "USDC"
    }'
  ```
</CodeGroup>

`network` is validated against the **credential's own** currency, not the wallet's. So an `NGN` credential uses `bank`; a `USDC` credential uses `base` / `ethereum` / `solana`.

## Eligibility

Cross-currency is admitted only when **every** condition below holds. Any failure returns a `400` with `invalid_input`.

* The pair must be **crypto ↔ fiat**. Crypto ↔ crypto and fiat ↔ fiat are rejected.
* **Both** currencies must advertise the matching direction capability:
  * Auto-onramp requires `canOnramp` on the credential currency AND on the wallet currency.
  * Auto-offramp requires `canOfframp` on both.
* The credential currency must resolve to a supported currency row. An unknown code returns `404` `not_found`.

<Note>
  The set of currencies that support `canOnramp` / `canOfframp` is fixed by GlobalStack. If your wallet's currency isn't eligible for a given direction, cross-currency provisioning will fail — reach out to support to confirm coverage.
</Note>

## Deposit lifecycle

Cross-currency deposits skip the `deposit.*` topics entirely. The first webhook you receive is `conversion.created` (or `conversion.funds_received` — whichever the FX pipeline emits first for the run); the deposit terminals via the `conversion.*` topics:

| Event                       | When it fires                             | Meaning                                                                                                                   |
| --------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `conversion.created`        | Conversion quote issued                   | The FX conversion is registered against the deposit; rate is locked.                                                      |
| `conversion.funds_received` | FX Engine has custody of the source funds | The FX-side settlement leg is queued.                                                                                     |
| `conversion.processing`     | Conversion is executing                   | Money is moving through the FX rails.                                                                                     |
| `conversion.success`        | Conversion settled                        | The **wallet balance** has been credited in the wallet's currency.                                                        |
| `conversion.failed`         | Conversion did not settle                 | Funds are parked on the credential balance until GlobalStack drains it (see [Recovery on failure](#recovery-on-failure)). |
| `conversion.returned`       | Conversion reversed after success         | Same "funds parked, contact support" recovery as `conversion.failed`.                                                     |

Same-currency credentials keep the original lifecycle across the `deposit.*` topics — `deposit.received` on arrival, then `deposit.held` if a tier gate applies, then `deposit.confirmed` when the credit settles (or `deposit.failed` if it doesn't). Cross-currency credentials **never** fire any `deposit.*` topic.

<Info>
  Rate is locked at deposit time. The `destination_amount` you see on `conversion.success` reflects the rate as of the deposit's arrival, not the rate as of the auto-conversion attempt.
</Info>

## Fees

Auto-conversion fees follow the FX conversion contract: the destination amount is **net of fees**, and the fee breakdown is on the `conversion.*` webhook payloads. See [failure reasons](/api-reference/failure-reasons) for the codes surfaced on a failed conversion.

## Recovery on failure

If `conversion.failed` (or `conversion.returned`) fires, funds stay on the credential's own balance — no auto-retry (FX failures are typically structural, not transient). Contact GlobalStack support to drain the parked funds; ops will run a fresh conversion at the then-current rate. Once the drain lands, the wallet balance is credited and the credential balance clears.

<Warning>
  There is no merchant-facing "retry" or "refund" endpoint in v1. Recovery goes through GlobalStack support.
</Warning>

## When to use auto-conversion

Reach for auto-conversion when your payers want to pay in a familiar local currency but your treasury runs in a different one — the classic example is accepting NGN bank deposits into a USDC treasury without a manual conversion step per deposit. If your payers already hold funds in the same currency as your wallet, stick with same-currency credentials: they credit the wallet directly with no FX exposure.
