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

# Transaction Handling

> How to prevent duplicate payments, retry safely, reconcile uncertain outcomes, handle failures, and understand fees and refunds with the Fapshi API.

***

This page explains how Fapshi treats the transactions you create, and what your application is responsible for to keep transaction states reliable. Read it before going live with [Initiate Pay](https://docs.fapshi.com/en/api-reference/endpoint/initiate-pay.md), [Direct Pay](https://docs.fapshi.com/en/api-reference/endpoint/direct-pay.md) or [Payout](https://docs.fapshi.com/en/api-reference/endpoint/payout.md).

## Idempotency and Duplicate Prevention

> [!WARNING]
>
> Fapshi does **not** support idempotency keys, and it does **not** enforce uniqueness of `externalId` (or `userId`). Every successful call to a transaction creation endpoint creates a **new, independent transaction**, even if you send exactly the same body twice.

This means:

* If you send two [Direct Pay](https://docs.fapshi.com/en/api-reference/endpoint/direct-pay.md) requests with the same `externalId`, Fapshi creates two transactions and sends two payment prompts to the customer. Both can be paid.
* If you send two [Payout](https://docs.fapshi.com/en/api-reference/endpoint/payout.md) requests with the same `externalId`, both payouts are processed.
* Preventing duplicates is **your application's responsibility**.

### Recommended approach

1. Generate a unique `externalId` in your system for every payment attempt (e.g., your order ID plus an attempt number) and **store it before** calling Fapshi.
2. Always send a `userId` as well. It is what lets you look the transaction up later if you never receive the response (see below).
3. Store the `transId` returned by Fapshi against your `externalId` as soon as you receive it.
4. Do not create a new transaction for an order that already has one that is `CREATED`, `PENDING` or `SUCCESSFUL`.

### Retrying after a timeout or lost response

If a transaction creation request times out or you never receive its response, **do not blindly resend it**. The transaction may already exist. Instead:

1. Call [`GET /transaction/{userId}`](https://docs.fapshi.com/en/api-reference/endpoint/transaction-by-user) with the `userId` you sent.
2. Look for a transaction whose `externalId` matches the one you sent.
3. **If you find it**, save its `transId` and continue tracking that transaction. Do not retry.
4. **If you do not find it**, the transaction was not created and it is safe to send the request again.

> [!NOTE]
>
> A transaction is returned by [`GET /transaction/{userId}`](https://docs.fapshi.com/en/api-reference/endpoint/transaction-by-user) as soon as it is created (status `CREATED`), so you can run this check immediately, even if the original API response was lost.

## Transaction States

| Status | Final? | Meaning |
| :- | :- | :- |
| CREATED | No | The transaction exists but no payment attempt has been made yet. |
| PENDING | No | The customer is in the process of paying (e.g., a payment prompt has been sent to their phone). |
| SUCCESSFUL | Yes | The payment completed. The **full `amount` you passed to the API** was collected (Fapshi does not collect partial payments). |
| FAILED | Yes for Direct Pay | The payment attempt failed. See [Failed transactions](#failed-transactions). |
| EXPIRED | Yes | Only for payment links: 24 hours passed without a successful payment, or the link was [manually expired](https://docs.fapshi.com/en/api-reference/endpoint/expire-pay.md). |

* [Direct Pay](https://docs.fapshi.com/en/api-reference/endpoint/direct-pay.md) transactions never expire. Their final state is always `SUCCESSFUL` or `FAILED`.
* [Payment links](https://docs.fapshi.com/en/api-reference/endpoint/initiate-pay.md) expire after 24 hours. Until then, a customer can retry on the same link after a failed attempt.

To track state changes, use [webhooks](https://docs.fapshi.com/en/api-reference/endpoint/webhook.md) as your primary signal and [`GET /payment-status/{transId}`](https://docs.fapshi.com/en/api-reference/endpoint/payment-status) to confirm or to recover missed notifications.

## Failed Transactions

> [!WARNING]
>
> A `FAILED` status does **not** tell you *why* a payment failed. Fapshi does not distinguish between a declined payment, insufficient funds, a cancelled prompt, or a prompt the customer ignored. The messages returned by the mobile money operators are usually vague, so the exact cause cannot be determined with certainty.

Recommended handling:

* Treat `FAILED` as a final outcome for that transaction.
* Show the customer a generic message (e.g., *"The payment could not be completed. Please check your balance and try again."*).
* If the customer wants to try again, create a **new** transaction with a new `externalId`.

## Reconciliation Checklist

Use this checklist to reconcile payments whose outcome is uncertain:

| Situation | What to do |
| :- | :- |
| Creation request timed out / response lost | Look up by `userId` + `externalId` as described in [Retrying after a timeout](#retrying-after-a-timeout-or-lost-response). |
| You have a `transId` but no webhook arrived | Call [`GET /payment-status/{transId}`](https://docs.fapshi.com/en/api-reference/endpoint/payment-status). Webhooks are not retried automatically. |
| You want to review many transactions | Use [`GET /search`](https://docs.fapshi.com/en/api-reference/endpoint/search-transactions) (status, medium, date range, amount). |
| A webhook failed to reach your server | Resend it manually from the Fapshi dashboard, or query the payment status. See [Webhooks](https://docs.fapshi.com/en/api-reference/endpoint/webhook.md). |
| `GET /payment-status/{transId}` returns 400 or 404 | The `transId` is invalid or was never issued by Fapshi. See [Payment Status](https://docs.fapshi.com/en/api-reference/endpoint/payment-status.md#error-responses). |

## Amounts and Fees

* **Fapshi does not collect partial payments.** Fapshi always collects the full `amount` you pass to the API, so a transaction marked `SUCCESSFUL` always means that exact amount was collected.
* Fapshi's transaction fee is **3% of the amount paid**.
* The fee is the same for every payment method (MTN Mobile Money and Orange Money) and does **not** change with transaction volume.
* The `revenue` field on a transaction is what you receive after Fapshi fees are deducted:

```
revenue = amount − fees      (fees = 3% of amount)
```

For example, a successful payment of `10,000 XAF` has `revenue` of `9,700 XAF`.

For settlement timelines and other pricing questions, see the [Fapshi FAQ](https://www.fapshi.com/en/faq).

## Refunds

Fapshi does **not** have a dedicated refund API. To return money to a customer, send it to them with the [Payout endpoint](https://docs.fapshi.com/en/api-reference/endpoint/payout.md), using a **separate payout-enabled service**.

The refund is paid from your payout service balance, not from the collections service that received the original payment. Make sure the payout service is funded first (an instant, free transfer from your collections service, or a top-up); see [Funding Your Payout Service](https://docs.fapshi.com/en/api-reference/endpoint/payout.md#funding-your-payout-service).

> [!NOTE]
>
> Payouts are disabled by default in the live environment and must be activated. The requirements and restrictions are described on the [Payout endpoint page](https://docs.fapshi.com/en/api-reference/endpoint/payout.md). Remember that payouts are subject to the same rule as payments: Fapshi does not prevent duplicate payouts, so apply the same duplicate-prevention approach described above.

## Supported Payment Methods

The API supports **MTN Mobile Money** and **Orange Money** only (plus Fapshi accounts as a payout destination). There are no plans to support other payment networks in the short term.

***

Need help? Contact us via [support@fapshi.com](mailto:support@fapshi.com) or visit our [Help & Support Center](https://fapshi.com/en/help-and-support).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.