# Custodial vs. Non-Custodial Off-Ramp

For the off-ramp (sell) flow, there are two ways to handle the crypto transfer from the customer to Banxa. The right choice depends on whether your platform holds custody of your customers' crypto.


```mermaid
flowchart TD
    A([Sell order initiated]) --> B[POST /v2/sell]
    B --> C[Customer completes checkout<br/>KYC + bank account details]
    C --> D{Custodial?}

    D -->|No| E[Banxa shows deposit<br/>address + QR code]
    E --> F[Customer sends crypto<br/>from their own wallet]
    F --> Z

    D -->|Yes| G{Notification method}

    G -->|Deeplink| H[Banxa redirects to partner<br/>with deposit address in deeplink]
    H --> I[Partner transfers crypto<br/>to Banxa deposit address]
    I --> Z

    G -->|Webhook| J[Order status → waitingPayment<br/>Webhook fires to partner endpoint]
    J --> K[Partner calls GET /v2/orders/:id<br/>retrieves deposit address]
    K --> L[Partner transfers crypto<br/>to Banxa deposit address]
    L --> Z

    Z[Banxa detects on-chain transfer] --> M([Fiat payout released to customer])
```

## Non-custodial flow

The customer initiates the crypto transfer themselves. Banxa displays a receiving wallet address and QR code during checkout, and the customer sends the crypto directly from their own wallet.

**How it works:**

1. Customer creates a sell order and completes checkout (KYC, bank account details).
2. Banxa displays a deposit address and QR code.
3. Customer transfers the crypto from their wallet to the Banxa deposit address.
4. Banxa detects the incoming transfer on-chain and processes the fiat payout.


**No additional API calls are required from your platform** after order creation.

**Best for:**

- Self-custody wallets where the customer controls their private keys.
- Consumer wallet applications.


## Custodial flow

Your platform holds custody of the customer's crypto and executes the blockchain transfer on their behalf. After the customer completes checkout, Banxa needs to notify your platform of the deposit address. There are two ways this works:

### Option 1: Deeplink

1. Customer creates a sell order and completes checkout (KYC, bank account details).
2. Banxa redirects back to your platform via a deeplink that includes the deposit address and all required transfer parameters.
3. Your platform reads the deeplink parameters and executes the blockchain transfer to Banxa's deposit address.
4. Banxa detects the incoming transfer on-chain and processes the fiat payout.


**Example deeplink:**


```
https://example.com/banxa/?blockchain=ETH&coinAmount=39.29&fiatAmount=55
  &fulfillmentStatus=Pending&providerWalletAddress=0x03EA4c7ED1d8199510017D88f2783Ef43ab5a4fd
  &coinType=USDT&orderId=7dbb7f5c2ad8bbbd022e4426fe98fb3a&identityStatus=Complete
  &orderRef=7dbb7f5c2ad8bbbd022e4426fe98fb3a&paymentStatus=Action%2BRequired
  &coin=USDT&orderStatus=pending&fiat=AUD
```

Your platform uses `providerWalletAddress` as the destination address for the blockchain transfer, and `coinAmount` as the amount to send.

### Option 2: Webhook

1. Customer creates a sell order and completes checkout (KYC, bank account details).
2. Banxa updates the order status to `waitingPayment` and triggers a webhook to your endpoint.
3. Your platform calls `GET /v2/orders/{id}` to retrieve the deposit address and transfer details.
4. Your platform executes the blockchain transfer to Banxa's deposit address.
5. Banxa detects the incoming transfer on-chain and processes the fiat payout.


Contact Banxa to discuss which option is best for your integration.

**Best for:**

- Exchanges or custodial wallet products where your platform manages customer funds.
- Cases where you want to automate the crypto transfer without customer action.


## Choosing a flow

Contact Banxa to configure your preferred flow. The flow is set at the partner account level and applies to all sell orders for your integration.

| Consideration | Non-custodial | Custodial |
|  --- | --- | --- |
| You hold customer crypto | No | Yes |
| Customer action required for transfer | Yes | No |
| Webhook integration required | Optional | Yes |