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

# OPay charge

> Accept NGN payments through OPay, including the redirect authorisation step.

Use OPay Charge to collect Nigerian naira payments through OPay. Charges are processed
asynchronously — after you initiate one, Zerocash briefly checks for the first actionable state
before responding.

<Tip>
  Use [Bank Transfer](/guides/collections/bank-transfer) instead when the customer should pay into
  a temporary account rather than through an OPay wallet.
</Tip>

## Happy path

<Steps>
  <Step title="Initiate the charge">
    Send the amount, an optional customer email, and your `externalReference`.
  </Step>

  <Step title="Redirect if asked">
    If the response carries `stepRequired: "redirect"`, send the customer to `redirectUrl`.
  </Step>

  <Step title="Confirm">
    Listen for the webhook or query the transaction status.
  </Step>

  <Step title="Fulfil">
    Only once `chargeStatus` is `successful`.
  </Step>
</Steps>

## 1. Initiate the charge

Send a request to [Opay Charge](/api-reference/endpoint/opay-charge).

| Field                | Type   | Required | Description                                |
| :------------------- | :----- | :------: | :----------------------------------------- |
| `amount`             | Number |    Yes   | Amount to charge, e.g. `100`               |
| `externalReference`  | String |    Yes   | Your own unique reference                  |
| `currency`           | String |     —    | `NGN`. Defaults to `NGN`                   |
| `email`              | String |     —    | Customer email                             |
| `successRedirectUrl` | String |     —    | Where to return the customer after success |
| `failureRedirectUrl` | String |     —    | Where to return the customer after failure |

<CodeGroup>
  ```json Required fields theme={null}
  {
    "amount": 100,
    "externalReference": "nvcmnvnmclmlv"
  }
  ```

  ```json All fields theme={null}
  {
    "amount": 100,
    "currency": "NGN",
    "email": "hal.jordan@gmail.com",
    "externalReference": "nvcmnvnmclmlv",
    "successRedirectUrl": "https://www.example.com/success",
    "failureRedirectUrl": "https://www.example.com/failed"
  }
  ```
</CodeGroup>

```json Response theme={null}
{
  "success": true,
  "message": "Transaction initiated successfully.",
  "data": {
    "transactionId": "6VOWReShlbh4MzXu8kbQ"
  }
}
```

## 2. Handle the initial response

The initial response comes back in one of two states.

<CodeGroup>
  ```json Pending theme={null}
  {
    "success": true,
    "message": "Transaction initiated successfully.",
    "data": {
      "transactionId": "txn_123",
      "status": "PENDING",
      "chargeStatus": "pending"
    }
  }
  ```

  ```json Redirect required theme={null}
  {
    "success": true,
    "message": "Transaction initiated successfully.",
    "data": {
      "transactionId": "txn_123",
      "status": "PENDING",
      "chargeStatus": "pending",
      "stepRequired": "redirect",
      "redirectUrl": "https://checkout.example.com/pay"
    }
  }
  ```
</CodeGroup>

| State                 | What it means                                | What you do                                                                |
| :-------------------- | :------------------------------------------- | :------------------------------------------------------------------------- |
| **Pending**           | No redirect or final status is available yet | Store the `transactionId` and wait for a webhook, or query Get Transaction |
| **Redirect required** | An authorisation URL is ready                | Send the customer to `redirectUrl`                                         |

## 3. Redirect the customer

When the response includes `stepRequired: "redirect"`, send your customer to `redirectUrl` to
authorise the payment.

<Warning>
  After the customer finishes, do **not** rely on the redirect back to your application. Confirm
  the final status through a webhook or
  [Get Transaction](/api-reference/endpoint/get-transaction).
</Warning>

## 4. Verify the transaction status

Query with the `transactionId` or your `externalReference`.

<CodeGroup>
  ```json Redirect required theme={null}
  {
    "success": true,
    "data": {
      "transactionId": "ARKHAM-ASYLUM-777",
      "amount": 500,
      "currency": "NGN",
      "createdAt": 1772739766529,
      "chargeStatus": "pending",
      "receiverCurrency": "NGN",
      "receiverAmount": 500,
      "senderCurrency": "NGN",
      "senderAmount": 500,
      "status": "PENDING",
      "type": "deposit",
      "method": "opay",
      "fullTimestamp": "2026-03-05T19:42:46+00:00",
      "externalReference": "PUDDIN-01",
      "stepRequired": "redirect",
      "redirectUrl": "https://redirect.com"
    }
  }
  ```

  ```json Successful theme={null}
  {
    "success": true,
    "data": {
      "transactionId": "lBK9bMny2gs4hLsG3XGq",
      "amount": 25,
      "type": "deposit",
      "currency": "NGN",
      "senderCurrency": "NGN",
      "senderAmount": 25,
      "receiverCurrency": "NGN",
      "receiverAmount": 25,
      "chargeStatus": "successful",
      "status": "SUCCESSFUL",
      "method": "opay",
      "fullTimestamp": "2025-06-17T01:16:44+03:00",
      "externalReference": "test",
      "phoneNumber": "253722446688"
    }
  }
  ```
</CodeGroup>

## 5. Handle webhooks

```json Redirect required theme={null}
{
  "event": "transaction_updated",
  "data": {
    "transactionId": "RFJZcgeeTGilZgPp9zyn",
    "status": "pending",
    "type": "deposit",
    "stepRequired": "redirect",
    "externalReference": "12fd3456789x",
    "redirectUrl": "https://redirect.com"
  },
  "timestamp": "2026-03-05T19:42:56.538Z"
}
```

## Testing in sandbox

Direct sandbox OPay charges are **redirect-first** — every initiation response includes
`stepRequired: "redirect"` and a `redirectUrl`. Opening that URL completes the simulated
transaction.

| Amount           | Outcome                             |
| :--------------- | :---------------------------------- |
| `111`            | Successful transaction              |
| `999`            | Failed transaction                  |
| Any other amount | Follows the failed redirect outcome |

See [Testing direct collection APIs](/guides/testing/direct-collections) for the complete sandbox
flow.
