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

# B2C Transfer Quick Start

> Get up and running with B2C transfers

# B2C Transfer Quick Start

## Prerequisites

* **Merchant Account**: Contact sales for a GoPay merchant account
* **API Key Pair**: Create an Ed25519 key pair with the `b2c` permission — see [Authentication](/getting-started/authentication#api-keys)
* **Funded Wallet**: Transfers are debited from your merchant wallet balance
* **Server Environment**: A backend to securely sign and send API requests

## Implementation Steps

<Tabs>
  <Tab title="Step 1: Sign the Request">
    B2C requests use the same Ed25519 header-based authentication as every GoPay API — only the key permission differs (`b2c`).

    Follow the [Authentication](/getting-started/authentication) guide: hash the exact body bytes, build the [v1 canonical string](/getting-started/authentication#the-canonical-string-v1), sign with your private key, and send the `X-Public-Key`, `X-Signature`, `X-Timestamp`, and `X-Request-ID` headers. Ready-to-use signing helpers for Node.js, Python, and Go are on that page.
  </Tab>

  <Tab title="Step 2: Transfer Request">
    Send a POST request to `/api/v1/initiate-transfer`:

    | Parameter               | Type   | Required | Description                                      |
    | ----------------------- | ------ | -------- | ------------------------------------------------ |
    | `mer_id`                | string | Yes      | Your merchant ID                                 |
    | `amount`                | number | Yes      | Transfer amount (> 0)                            |
    | `currency`              | string | Yes      | Currency code, e.g. `ETB`                        |
    | `reason`                | string | Yes      | Purpose of the transfer                          |
    | `receiver_phone_number` | string | Yes      | Recipient phone: `09XXXXXXXX` or `+2519XXXXXXXX` |
    | `client_reference`      | string | Yes      | Your unique reference for this transfer          |
    | `notify_url`            | string | Yes      | Absolute HTTPS URL for the settlement webhook    |
    | `bank_id`               | string | Yes      | Payout rail identifier (see below)               |

    Supported payout rails:

    | `bank_id` | Rail              |
    | --------- | ----------------- |
    | `1`       | Telebirr          |
    | `2`       | CBE Birr          |
    | `3`       | Awash Bank        |
    | `4`       | Dashen Bank       |
    | `5`       | Bank of Abyssinia |
  </Tab>

  <Tab title="Step 3: Handle Response">
    On success (200 OK):

    ```json theme={null}
    {
        "message": "B2C transaction initiated successfully",
        "txn_id": "b2c_tx_6fcb15a983c54a7e97b1",
        "status": "pending"
    }
    ```

    1. Save `txn_id` — settlement webhooks reference it
    2. The transfer is asynchronous: initiation success means the request was accepted and your wallet debited, not that the recipient has been paid
    3. The final result (`completed` / `failed`) arrives as a signed webhook on your `notify_url` — see [B2C Callbacks](/webhooks/b2c-callbacks)

    On error you receive the [standard error shape](/getting-started/errors). One code is specific to transfers: `INSUFFICIENT_FUNDS` (HTTP 402) means your merchant wallet balance cannot cover the transfer — top up and retry with a fresh `X-Request-ID`.
  </Tab>
</Tabs>

## Next Steps

<CardGroup cols={2}>
  <Card title="API Reference" icon="code" href="/transfers/api-reference">
    Full request/response contract and validation rules
  </Card>

  <Card title="Code Examples" icon="file-code" href="/transfers/examples">
    Complete initiate-transfer calls in Node.js, Python, and Go
  </Card>
</CardGroup>
