> For the complete documentation index, see [llms.txt](https://docs.fonbnk.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fonbnk.com/countries/philippines/bank-transfer.md).

# Bank transfer

How to off-ramp PHP with bank transfer in Philippines: fields, limits and API examples.

| countryIsoCode | currencyIsoCode | paymentChannel | Typical settlement |
| -------------- | --------------- | -------------- | ------------------ |
| `PH`           | `PHP`           | `bank`         | —                  |

{% hint style="warning" %}
The walkthroughs ran in sandbox on 2026-10-09. The limits, fields and KYC rules are a snapshot of production on 2026-10-09. They change when providers change, so build against [Get available currencies](/server-to-server/api-endpoints/get-available-currencies.md) and the `fieldsToCreateOrder` of each quote, not against this page.
{% endhint %}

| Route                                | Per order (production) | Transfer type |
| ------------------------------------ | ---------------------- | ------------- |
| Off-ramp, Bank transfer (`ph_gcash`) | 100 to 30,697.62 PHP   | —             |

Before the first call: set up the keys and the signing helpers from [Countries](/countries.md), and verify the user as [Philippines](/countries/philippines.md) explains.

## Off-ramp

### 1. Get a quote

The quote fixes the rate and lists the fields to collect from the user. Use it before `quoteExpiresAt`, or get a new one.

{% tabs %}
{% tab title="curl" %}
{% code overflow="wrap" %}

```bash
ENDPOINT='/api/v2/quote'
TIMESTAMP=$(($(date +%s) * 1000))
curl -X POST "$FONBNK_BASE_URL$ENDPOINT" \
  -H "x-client-id: $FONBNK_CLIENT_ID" \
  -H "x-timestamp: $TIMESTAMP" \
  -H "x-signature: $(fonbnk_sign "$TIMESTAMP" "$ENDPOINT")" \
  -H "Content-Type: application/json" \
  --data '{"deposit":{"paymentChannel":"crypto","currencyType":"crypto","currencyCode":"CELO_USDT"},"payout":{"paymentChannel":"bank","currencyType":"fiat","currencyCode":"PHP","countryIsoCode":"PH","carrierCode":"ph_gcash","amount":400}}'
```

{% endcode %}
{% endtab %}

{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript
const response = await fonbnkRequest('POST', '/api/v2/quote', {
  "deposit": {
    "paymentChannel": "crypto",
    "currencyType": "crypto",
    "currencyCode": "CELO_USDT"
  },
  "payout": {
    "paymentChannel": "bank",
    "currencyType": "fiat",
    "currencyCode": "PHP",
    "countryIsoCode": "PH",
    "carrierCode": "ph_gcash",
    "amount": 400
  }
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% code title="Response (sandbox, fee amounts and long lists cut)" overflow="wrap" expandable="true" %}

```json
{
  "quoteId": "665000000000000000000018",
  "quoteExpiresAt": "2026-10-09T12:35:00.000Z",
  "deposit": {
    "paymentChannel": "crypto",
    "currencyType": "crypto",
    "currencyCode": "CELO_USDT",
    "currencyDetails": {
      "network": "CELO",
      "asset": "USDT",
      "contractAddress": "0xd5cf8ab08295e32db2e2dce8478e5ce021340a57"
    },
    "cashout": {
      "amountBeforeFees": 6.546595,
      "amountAfterFees": 6.546595,
      "amountBeforeFeesUsd": 6.546595,
      "amountAfterFeesUsd": 6.546595,
      "exchangeRate": 1,
      "exchangeRateAfterFees": 1,
      "feeSettings": []
    },
    "fieldsToCreateOrder": [
      {
        "key": "blockchainWalletAddress",
        "type": "string",
        "label": "Your wallet address",
        "required": false
      },
      {
        "key": "depositSandboxForcedFlow",
        "type": "enum",
        "label": "Sandbox deposit forced flow",
        "required": false,
        "defaultValue": "deposit_success",
        "options": [
          {
            "label": "Deposit success",
            "value": "deposit_success"
          },
          {
            "label": "Deposit invalid",
            "value": "deposit_invalid"
          },
          {
            "label": "Deposit invalid: transfer not found",
            "value": "deposit_crypto_transfer_not_found"
          }
        ]
      }
    ],
    "transferType": "manual"
  },
  "payout": {
    "paymentChannel": "bank",
    "currencyType": "fiat",
    "currencyCode": "PHP",
    "currencyDetails": {
      "countryIsoCode": "PH"
    },
    "cashout": {
      "amountBeforeFees": 412.37,
      "amountAfterFees": 400,
      "amountBeforeFeesUsd": 6.546595,
      "amountAfterFeesUsd": 6.350214,
      "exchangeRate": 62.99,
      "exchangeRateAfterFees": 64.938,
      "feeSettings": [
        {
          "id": "provider_fee",
          "type": "percentage",
          "recipient": "provider"
        },
        {
          "id": "service_fee",
          "type": "percentage",
          "recipient": "platform"
        }
      ]
    },
    "fieldsToCreateOrder": [
      {
        "key": "phoneNumber",
        "label": "Phone Number",
        "required": true,
        "type": "phone"
      },
      {
        "key": "bankCode",
        "label": "Bank name",
        "required": true,
        "type": "enum",
        "options": [
          {
            "label": "Sandbox Bank",
            "value": "1"
          },
          {
            "label": "Sandbox Bank 2",
            "value": "2"
          },
          {
            "label": "Sandbox Bank 3",
            "value": "3"
          }
        ]
      },
      {
        "key": "bankAccountNumber",
        "label": "Bank Account Number",
        "required": true,
        "type": "string"
      },
      {
        "key": "payoutSandboxForcedFlow",
        "type": "enum",
        "label": "Sandbox payout forced flow",
        "required": false,
        "defaultValue": "payout_success",
        "options": [
          {
            "label": "Payout success",
            "value": "payout_success"
          },
          {
            "label": "Payout failed",
            "value": "payout_failed"
          }
        ]
      }
    ]
  }
}
```

{% endcode %}

In production the quote asks for these fields:

| Field                     | Label                    | Type     | Required | Example                                      |
| ------------------------- | ------------------------ | -------- | -------- | -------------------------------------------- |
| `blockchainWalletAddress` | Your wallet address      | `string` | No       | `0x5b7ae3c6c87f4a3f94b35c77233b13191ebfad20` |
| `phoneNumber`             | Phone Number             | `phone`  | Yes      | `639171234567`                               |
| `bankAccountHolderName`   | Bank Account Holder Name | `string` | Yes      | `Maria Santos`                               |
| `carrierCode`             | Bank or e-wallet         | `enum`   | Yes      | `ph_gcash`                                   |
| `bankAccountNumber`       | Bank Account Number      | `string` | Yes      | `0123456789`                                 |

Sandbox does not ask for `bankAccountHolderName`, `carrierCode`. Production does, so send them there.

### 2. Create the order

Send `quoteId` from the quote, and every required field of both legs as one flat `fieldsToCreateOrder` object.

{% tabs %}
{% tab title="curl" %}
{% code overflow="wrap" %}

```bash
ENDPOINT='/api/v2/order'
TIMESTAMP=$(($(date +%s) * 1000))
curl -X POST "$FONBNK_BASE_URL$ENDPOINT" \
  -H "x-client-id: $FONBNK_CLIENT_ID" \
  -H "x-timestamp: $TIMESTAMP" \
  -H "x-signature: $(fonbnk_sign "$TIMESTAMP" "$ENDPOINT")" \
  -H "Content-Type: application/json" \
  --data '{"quoteId":"665000000000000000000018","userEmail":"user@example.com","userIp":"102.89.23.10","userCountryIsoCode":"PH","deposit":{"paymentChannel":"crypto","currencyType":"crypto","currencyCode":"CELO_USDT"},"payout":{"paymentChannel":"bank","currencyType":"fiat","currencyCode":"PHP","countryIsoCode":"PH","carrierCode":"ph_gcash","amount":400},"fieldsToCreateOrder":{"phoneNumber":"639171234567","bankCode":"1","bankAccountNumber":"0123456789"},"orderParams":"my-order-offramp-bank"}'
```

{% endcode %}
{% endtab %}

{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript
const response = await fonbnkRequest('POST', '/api/v2/order', {
  "quoteId": "665000000000000000000018",
  "userEmail": "user@example.com",
  "userIp": "102.89.23.10",
  "userCountryIsoCode": "PH",
  "deposit": {
    "paymentChannel": "crypto",
    "currencyType": "crypto",
    "currencyCode": "CELO_USDT"
  },
  "payout": {
    "paymentChannel": "bank",
    "currencyType": "fiat",
    "currencyCode": "PHP",
    "countryIsoCode": "PH",
    "carrierCode": "ph_gcash",
    "amount": 400
  },
  "fieldsToCreateOrder": {
    "phoneNumber": "639171234567",
    "bankCode": "1",
    "bankAccountNumber": "0123456789"
  },
  "orderParams": "my-order-offramp-bank"
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% code title="Response (sandbox, order fields cut)" overflow="wrap" expandable="true" %}

```json
{
  "quoteUsed": true,
  "order": {
    "_id": "665000000000000000000019",
    "status": "deposit_awaiting",
    "expiresAt": "2026-10-09T12:35:00.000Z",
    "deposit": {
      "paymentChannel": "crypto",
      "currencyType": "crypto",
      "currencyCode": "CELO_USDT",
      "currencyDetails": {
        "network": "CELO",
        "asset": "USDT",
        "contractAddress": "0xd5cf8ab08295e32db2e2dce8478e5ce021340a57"
      },
      "cashout": {
        "exchangeRate": 1,
        "feeSettings": [],
        "exchangeRateAfterFees": 1,
        "amountBeforeFees": 6.546595,
        "amountAfterFees": 6.546595,
        "amountBeforeFeesUsd": 6.546595,
        "amountAfterFeesUsd": 6.546595
      },
      "providedFieldsToCreateOrder": {},
      "transferInstructions": {
        "type": "manual",
        "instructionsText": "Please send the exact amount of crypto to the address below. Make sure to send only USDT on the Celo network. Sending any other assets or using a different network may result in loss of funds.",
        "transferDetails": [
          {
            "id": "recipientWalletAddress",
            "label": "Wallet address to send",
            "value": "<the deposit address of your order>"
          },
          {
            "id": "senderWalletAddress",
            "label": "Your wallet address"
          },
          {
            "id": "amountToSend",
            "label": "Amount to send",
            "value": "6.546595"
          },
          {
            "id": "cryptoTransactionRequestAdditionalData",
            "label": "Crypto transaction additional data",
            "value": ""
          }
        ],
        "fieldsToConfirmOrder": [
          {
            "key": "blockchainTransactionHash",
            "type": "string",
            "label": "Transaction hash",
            "required": true
          }
        ]
      },
      "formattedUserFieldsToCreateOrder": [
        {
          "key": "blockchainWalletAddress",
          "label": "Your wallet address",
          "value": null,
          "type": "string"
        },
        {
          "key": "depositSandboxForcedFlow",
          "label": "Sandbox deposit forced flow",
          "value": null,
          "type": "enum"
        }
      ]
    }
  }
}
```

{% endcode %}

### 3. Receive the crypto

The user sends the crypto to the address in `order.deposit.transferInstructions`. Then call [Confirm order](/server-to-server/api-endpoints/confirm-order.md) with the fields in `transferInstructions.fieldsToConfirmOrder`, here the `blockchainTransactionHash` of that transfer. We check the transfer on-chain, and the payout starts when it is confirmed.

{% tabs %}
{% tab title="curl" %}
{% code overflow="wrap" %}

```bash
ENDPOINT='/api/v2/order/confirm'
TIMESTAMP=$(($(date +%s) * 1000))
curl -X POST "$FONBNK_BASE_URL$ENDPOINT" \
  -H "x-client-id: $FONBNK_CLIENT_ID" \
  -H "x-timestamp: $TIMESTAMP" \
  -H "x-signature: $(fonbnk_sign "$TIMESTAMP" "$ENDPOINT")" \
  -H "Content-Type: application/json" \
  --data '{"orderId":"665000000000000000000019","fieldsToConfirmOrder":{"blockchainTransactionHash":"0x9f996c47b5441520ced429d3f315c9eccd9c184f8e6dc1809c805a3677916418"}}'
```

{% endcode %}
{% endtab %}

{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript
const response = await fonbnkRequest('POST', '/api/v2/order/confirm', {
  "orderId": "665000000000000000000019",
  "fieldsToConfirmOrder": {
    "blockchainTransactionHash": "0x9f996c47b5441520ced429d3f315c9eccd9c184f8e6dc1809c805a3677916418"
  }
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% code title="Response (sandbox, status fields only)" overflow="wrap" %}

```json
{
  "_id": "665000000000000000000019",
  "status": "deposit_validating"
}
```

{% endcode %}

### 4. Wait for the final status

The [webhook](/server-to-server/webhooks.md) tells you each new status. To check an order, call [Get order](/server-to-server/api-endpoints/get-order.md). What to do at each status is on [Countries](/countries.md). Sandbox crypto runs on a test network and checks each deposit on-chain. The sample hash above matches no transfer, so this sandbox order stays in `deposit_validating`. Send a real test-network transfer to finish an off-ramp in sandbox.

{% tabs %}
{% tab title="curl" %}
{% code overflow="wrap" %}

```bash
ENDPOINT='/api/v2/order?orderId=665000000000000000000019'
TIMESTAMP=$(($(date +%s) * 1000))
curl "$FONBNK_BASE_URL$ENDPOINT" \
  -H "x-client-id: $FONBNK_CLIENT_ID" \
  -H "x-timestamp: $TIMESTAMP" \
  -H "x-signature: $(fonbnk_sign "$TIMESTAMP" "$ENDPOINT")"
```

{% endcode %}
{% endtab %}

{% tab title="TypeScript" %}
{% code overflow="wrap" %}

```typescript
const response = await fonbnkRequest('GET', '/api/v2/order?orderId=665000000000000000000019');
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% code title="Response (sandbox, status fields only)" overflow="wrap" %}

```json
{
  "_id": "665000000000000000000019",
  "status": "deposit_validating",
  "statusChangeLogs": [
    {
      "oldStatus": "deposit_awaiting",
      "newStatus": "deposit_validating",
      "date": "2026-10-09T12:05:00.000Z"
    }
  ]
}
```

{% endcode %}

## Testing in sandbox

Add one of these fields to `fieldsToCreateOrder` to force how a sandbox order ends, then run the walkthrough. Without them, a sandbox on-ramp succeeds. No real money moves.

| Route                                | Field                      | Values                                                                                                                                                                              |
| ------------------------------------ | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| On-ramp, Bank transfer (`ph_gcash`)  | `depositSandboxForcedFlow` | `deposit_success`, `deposit_invalid`, `deposit_underpayment`, `deposit_overpayment`, `deposit_payment_info_mismatch`                                                                |
| On-ramp, Bank transfer (`ph_gcash`)  | `payoutSandboxForcedFlow`  | `payout_success`, `payout_failed`                                                                                                                                                   |
| Off-ramp, Bank transfer (`ph_gcash`) | `depositSandboxForcedFlow` | `deposit_success`, `deposit_invalid`, `deposit_crypto_transfer_not_found`, `deposit_crypto_sender_mismatch`, `deposit_crypto_transfer_reverted`, `deposit_crypto_paid_before_order` |
| Off-ramp, Bank transfer (`ph_gcash`) | `payoutSandboxForcedFlow`  | `payout_success`, `payout_failed`                                                                                                                                                   |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.fonbnk.com/countries/philippines/bank-transfer.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
