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

# Transaction Lifecycle

> Understand how STK Push and B2C payout transactions move through their states.

# Transaction Lifecycle

Payments should not be a black box. Know exactly where every transaction is at all times.

Both STK Push and B2C payouts share the same state model. Understanding the lifecycle lets you handle every outcome correctly — including failures.

***

## Transaction states

| Status       | What it means                                                                     |
| ------------ | --------------------------------------------------------------------------------- |
| `PENDING`    | Request accepted. Waiting for customer action (STK) or provider acceptance (B2C). |
| `PROCESSING` | Provider accepted. Final confirmation pending.                                    |
| `SUCCESS`    | Complete. Funds moved.                                                            |
| `FAILED`     | Failed — provider declined, timeout, or customer cancelled.                       |
| `REVERSED`   | B2C wallet balance credited back after failure.                                   |
| `CANCELLED`  | Cancelled before processing began.                                                |

**Terminal states — no further updates:** `SUCCESS`, `FAILED`, `REVERSED`, `CANCELLED`

***

## STK Push lifecycle

```
POST /payments/stk
        │
        ▼
    PENDING ──── Customer receives phone prompt ──── Customer cancels
        │                                                │
    Customer enters PIN                         FAILED / CANCELLED
        │
        ▼
   PROCESSING ──── Provider processing ──── Provider timeout / error
        │                                           │
    M-Pesa confirms                              FAILED
        │
        ▼
    SUCCESS
```

**Typical completion:** 30–90 seconds after the customer enters their PIN.

| State        | What to do                                           |
| ------------ | ---------------------------------------------------- |
| `PENDING`    | Request sent. Wait for the customer to act.          |
| `PROCESSING` | PIN entered. Wait for M-Pesa confirmation.           |
| `SUCCESS`    | Fulfil the order.                                    |
| `FAILED`     | Notify the customer. Service fee is not refunded.    |
| `CANCELLED`  | Customer dismissed the prompt. Retry if appropriate. |

***

## B2C payout lifecycle

```
POST /b2c/payouts
        │
        ▼
    PENDING ──── Queued for processing
        │
        ▼
   PROCESSING ──── Provider sends to M-Pesa ──── Provider error / timeout
        │                                                │
    M-Pesa confirms                                  FAILED
        │                                                │
        ▼                                           REVERSED
    SUCCESS                                  (B2C balance credited back)
```

**Typical completion:** 30 seconds to 5 minutes.

| State        | What to do                                          |
| ------------ | --------------------------------------------------- |
| `PENDING`    | Request queued. No action needed.                   |
| `PROCESSING` | Provider accepted. Wait for M-Pesa.                 |
| `SUCCESS`    | Payout delivered.                                   |
| `FAILED`     | B2C wallet reversal is automatic. Retry when ready. |
| `REVERSED`   | Wallet credited. Safe to retry the payout.          |

***

## Receiving state updates

### Webhooks (recommended)

Supply a `callbackUrl` on every payment request. PalPluss delivers a `POST` to that URL when the transaction reaches a terminal state.

See the [Webhooks guide](/guides/webhooks) for payload structure and retry policy.

### Polling

Poll `GET /transactions/{id}` if webhooks are unavailable.

```bash theme={null}
curl https://api.palpluss.com/v1/transactions/{transactionId} \
  -u "$PALPLUSS_API_KEY:"
```

**Recommended polling intervals:**

1. Wait 15 seconds after initiation.
2. Poll every 10 seconds while status is `PENDING` or `PROCESSING`.
3. Stop at any terminal state.
4. After 5 minutes without a terminal state, treat the transaction as likely failed.

<Warning>
  Aggressive polling consumes your rate limit (60 requests/minute). Use webhooks as your primary mechanism.
</Warning>

***

## Idempotency

* Each `POST /payments/stk` creates a distinct transaction and a distinct M-Pesa checkout.
* Retrying without customer action sends a new prompt — do not retry unless the customer requests it.
* Service wallet top-ups support the `Idempotency-Key` header to prevent duplicate funding requests.
