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

# Execute Currency Exchange with Gcashier Pay FX API

> Lock in a real-time FX rate, execute the currency exchange in one confirmation call, and reconcile results via webhook — all within the Gcashier Pay FX API.

Gcashier Pay's FX API lets you convert balances between supported currencies at real-time interbank rates. The process is a straightforward two-step flow: first request a quote to lock in a rate, then confirm the trade before the quote expires. Results are delivered both synchronously in the confirmation response and asynchronously via the **sp3201** webhook. You can also query supported currency pairs and your full transaction history at any time.

<Note>
  All FX API calls require a valid **`accessToken`** in the request header, obtained after merchant onboarding is approved. Include it as: `Authorization: Bearer <accessToken>`.
</Note>

## Overview

<Steps>
  <Step title="Query supported currency pairs (sp2202)">
    Discover which sell/buy currency combinations are available for your account.
  </Step>

  <Step title="Request an FX quote (sp1201)">
    Lock in a rate for a specific amount and direction.
  </Step>

  <Step title="Execute the FX trade (sp1202)">
    Confirm the trade using the `quoteId` before it expires.
  </Step>

  <Step title="Receive the FX result webhook (sp3201)">
    Gcashier Pay posts the final settlement status to your callback URL.
  </Step>

  <Step title="Query FX history (sp2201)">
    Look up past transactions by quoteId or time range.
  </Step>
</Steps>

***

## Step 1 — Query Supported Currency Pairs

Before requesting a quote, call **POST /api/sp2202** to retrieve the currency pairs available on your account. This list can change as new corridors are activated, so query it dynamically rather than hard-coding pairs.

<CodeGroup>
  ```json sp2202 Request theme={null}
  {}
  ```

  ```json sp2202 Response theme={null}
  {
    "code": "S00000",
    "message": "success",
    "data": [
      { "sellCurrency": "USD", "buyCurrency": "CNY" },
      { "sellCurrency": "USD", "buyCurrency": "EUR" },
      { "sellCurrency": "EUR", "buyCurrency": "USD" },
      { "sellCurrency": "SGD", "buyCurrency": "USD" },
      { "sellCurrency": "HKD", "buyCurrency": "USD" }
    ]
  }
  ```
</CodeGroup>

Each object in `data` represents a tradeable pair. `sellCurrency` is the currency you spend; `buyCurrency` is the currency you receive.

***

## Step 2 — Request an FX Quote

Call **POST /api/sp1201** to obtain a rate-locked quote. You specify either the sell amount or the buy amount — set `lockDirection` accordingly.

| Field           | Required | Description                                                                |
| --------------- | -------- | -------------------------------------------------------------------------- |
| `merOrderNo`    | M        | Your unique reference for this quote request                               |
| `sellCurrency`  | O        | Currency you are selling (optional if implied by `buyCurrency`)            |
| `buyCurrency`   | M        | Currency you want to receive                                               |
| `lockDirection` | M        | `SELL` = you specify how much to sell; `BUY` = you specify how much to buy |
| `amount`        | M        | The amount to lock, in the currency implied by `lockDirection`             |

### Request / Response Example — Selling USD, Buying CNY

<CodeGroup>
  ```json sp1201 Request theme={null}
  {
    "merOrderNo": "FX20240601001",
    "sellCurrency": "USD",
    "buyCurrency": "CNY",
    "lockDirection": "SELL",
    "amount": "10000.00"
  }
  ```

  ```json sp1201 Response theme={null}
  {
    "merOrderNo": "FX20240601001",
    "sellCurrency": "USD",
    "buyCurrency": "CNY",
    "rate": "7.2415",
    "sellAmount": "10000.00",
    "buyAmount": "72415.00",
    "quoteId": "QT20240601000701",
    "expireTime": "1717228800000"
  }
  ```
</CodeGroup>

<Warning>
  The `expireTime` is a Unix timestamp in **milliseconds**. FX quotes are typically valid for 30 seconds. If you do not call sp1202 before `expireTime`, the quote will be invalidated and you must request a new one.
</Warning>

***

## Step 3 — Execute the FX Trade

Once you have a valid `quoteId`, confirm the trade by calling **POST /api/sp1202**. Pass the `quoteId` and your webhook URL for async result delivery.

<CodeGroup>
  ```json sp1202 Request theme={null}
  {
    "quoteId": "QT20240601000701",
    "callbackUrl": "https://api.acme-trade.com/webhooks/gcashier/fx-result"
  }
  ```

  ```json sp1202 Response theme={null}
  {
    "sellCurrency": "USD",
    "buyCurrency": "CNY",
    "rate": "7.2415",
    "sellAmount": "10000.00",
    "buyAmount": "72415.00",
    "quoteId": "QT20240601000701",
    "bizFlow": "BF20240601000702",
    "code": "S00001",
    "message": "FX trade submitted and processing."
  }
  ```
</CodeGroup>

The synchronous response confirms the trade has been accepted for settlement. The definitive success or failure result is delivered via the **sp3201** webhook.

<Tip>
  Build a retry-safe design: check whether a `bizFlow` already exists for a `quoteId` before re-submitting, since a quote can only be executed once.
</Tip>

***

## Step 4 — Receive the FX Result Webhook (sp3201)

Gcashier Pay posts the settlement outcome to your `callbackUrl` after the exchange is processed. Respond with HTTP 200 to acknowledge receipt.

<CodeGroup>
  ```json sp3201 Webhook — Success theme={null}
  {
    "bizFlow": "BF20240601000702",
    "quoteId": "QT20240601000701",
    "merOrderNo": "FX20240601001",
    "sellCurrency": "USD",
    "buyCurrency": "CNY",
    "rate": "7.2415",
    "sellAmount": "10000.00",
    "buyAmount": "72415.00",
    "status": "SUCC",
    "code": "S00000",
    "message": "FX trade settled successfully."
  }
  ```

  ```json sp3201 Webhook — Failed theme={null}
  {
    "bizFlow": "BF20240601000702",
    "quoteId": "QT20240601000701",
    "merOrderNo": "FX20240601001",
    "sellCurrency": "USD",
    "buyCurrency": "CNY",
    "status": "FAIL",
    "code": "E00010",
    "message": "Insufficient USD balance to complete trade."
  }
  ```
</CodeGroup>

| Status    | Meaning                                         |
| --------- | ----------------------------------------------- |
| `SUCC`    | Exchange completed — CNY balance credited       |
| `FAIL`    | Exchange failed — USD balance not debited       |
| `PROCESS` | Settlement in progress — wait for final webhook |

***

## Step 5 — Query FX History

Use **POST /api/sp2201** to look up past FX transactions. You can search by `quoteId` for a specific trade, or by a time range to retrieve all trades within a window.

<CodeGroup>
  ```json sp2201 Request — by quoteId theme={null}
  {
    "quoteId": "QT20240601000701"
  }
  ```

  ```json sp2201 Request — by time range theme={null}
  {
    "startTime": "2024-06-01 00:00:00",
    "endTime": "2024-06-01 23:59:59"
  }
  ```

  ```json sp2201 Response theme={null}
  {
    "code": "S00000",
    "message": "success",
    "data": [
      {
        "quoteId": "QT20240601000701",
        "bizFlow": "BF20240601000702",
        "merOrderNo": "FX20240601001",
        "sellCurrency": "USD",
        "buyCurrency": "CNY",
        "rate": "7.2415",
        "sellAmount": "10000.00",
        "buyAmount": "72415.00",
        "status": "SUCC",
        "tradeTime": "2024-06-01 14:32:10"
      }
    ]
  }
  ```
</CodeGroup>

<Note>
  Time range queries are limited to a **maximum window of 24 hours**. For historical reporting over longer periods, paginate by shifting the 24-hour window back in increments.
</Note>

***

## Sandbox Testing

In the Gcashier Pay sandbox environment, the settlement outcome of an FX trade is determined by the **last digit of the `amount`** in your sp1201 quote request:

| Last digit of `amount` | Simulated result                                 |
| ---------------------- | ------------------------------------------------ |
| `0` – `3`              | `SUCC` — exchange completes successfully         |
| `4` – `6`              | `FAIL` — exchange fails                          |
| `7` – `9`              | `PROCESS` — exchange remains in processing state |

For example, requesting a `sellAmount` of `10000.00` (last digit `0`) will trigger a successful settlement webhook in the sandbox.
