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

# POST /v1/billing/pay — Start a Card or M-Pesa Payment

> Initiate a Paystack card checkout, send an M-Pesa STK push, charge a saved payment method, or purchase a mail subscription plan — all through one endpoint.

Initiate a payment for an organization. The behavior depends on the `method` field in the request body. For mail subscriptions, the amount is always calculated server-side from the plan, seat count, and billing cycle — any client-provided `amount` is ignored.

## Endpoint

```
POST /v1/billing/pay
```

## Headers

<ParamField header="Authorization" type="string" required>
  Bearer token. Format: `Bearer <token>`
</ParamField>

<ParamField header="X-Organization-Id" type="string" required>
  The ID of the organization making the payment.
</ParamField>

## Request body

<ParamField body="method" type="string" required>
  Payment method to use. One of `card`, `mobile_money`, or `saved_method`.
</ParamField>

<ParamField body="amount" type="number">
  Amount in KES (whole units, not cents). Required for non-subscription payments. Ignored for `mail_subscription` — the server enforces the price.
</ParamField>

<ParamField body="phone" type="string">
  Kenyan M-Pesa phone number. Required when `method` is `mobile_money`. Only M-Pesa numbers are supported; Airtel numbers are rejected.
</ParamField>

<ParamField body="paymentMethodId" type="string">
  ID of a saved payment method. Required when `method` is `saved_method`.
</ParamField>

<ParamField body="metadata" type="object">
  Attach structured context to the payment. Required for mail subscription purchases.

  <Expandable title="properties">
    <ResponseField name="type" type="string">
      Set to `mail_subscription` to purchase a mailbox plan.
    </ResponseField>

    <ResponseField name="plan" type="string">
      Plan tier. One of `core`, `growth`, or `scale`.
    </ResponseField>

    <ResponseField name="seats" type="number">
      Number of mailboxes to purchase.
    </ResponseField>

    <ResponseField name="billingCycle" type="string">
      Billing frequency. One of `monthly` or `yearly`. Yearly billing applies a 2-month discount (10 months billed).
    </ResponseField>
  </Expandable>
</ParamField>

## Pricing reference

Prices are in KES per seat per month. The yearly total is 10× the monthly total.

| Seats     | Core | Growth | Scale |
| --------- | ---- | ------ | ----- |
| 1–50      | 100  | 150    | 220   |
| 51–500    | 80   | 130    | 200   |
| 501–5,000 | 60   | 110    | 180   |
| 5,001+    | 40   | 90     | 160   |

## Scenarios

<Tabs>
  <Tab title="New card checkout">
    Redirects the user to a Paystack-hosted card checkout page. Use the returned `checkoutUrl` to complete payment.

    ```bash theme={null}
    curl --request POST \
      --url https://api.nyotaimara.com/v1/billing/pay \
      --header 'Authorization: Bearer <token>' \
      --header 'X-Organization-Id: <org-id>' \
      --header 'Content-Type: application/json' \
      --data '{"method": "card", "amount": 5000}'
    ```

    ```json theme={null}
    {
      "success": true,
      "checkoutUrl": "https://checkout.paystack.com/...",
      "reference": "NI-550e8400-e29b-41d4-a716-446655440000"
    }
    ```
  </Tab>

  <Tab title="M-Pesa STK push">
    Sends an STK push prompt to the provided Kenyan M-Pesa number. The user enters their PIN on their phone to complete the payment.

    ```bash theme={null}
    curl --request POST \
      --url https://api.nyotaimara.com/v1/billing/pay \
      --header 'Authorization: Bearer <token>' \
      --header 'X-Organization-Id: <org-id>' \
      --header 'Content-Type: application/json' \
      --data '{"method": "mobile_money", "phone": "0712345678", "amount": 5000}'
    ```

    ```json theme={null}
    {
      "success": true,
      "message": "STK Push sent! Please check your phone to enter your M-Pesa PIN.",
      "reference": "NI-550e8400-e29b-41d4-a716-446655440000"
    }
    ```
  </Tab>

  <Tab title="Saved payment method">
    Charges a previously saved card or triggers an STK push to a previously saved M-Pesa number — no redirect or manual entry required.

    ```bash theme={null}
    curl --request POST \
      --url https://api.nyotaimara.com/v1/billing/pay \
      --header 'Authorization: Bearer <token>' \
      --header 'X-Organization-Id: <org-id>' \
      --header 'Content-Type: application/json' \
      --data '{"method": "saved_method", "paymentMethodId": "pm_01j9k2x...", "amount": 5000}'
    ```

    ```json theme={null}
    {
      "success": true,
      "message": "Payment processed successfully!"
    }
    ```
  </Tab>

  <Tab title="Mail subscription">
    Purchases a mailbox plan. Set `amount` to `0` — the server calculates the final charge from `metadata`. Use `method: "card"` to open a checkout page.

    ```bash theme={null}
    curl --request POST \
      --url https://api.nyotaimara.com/v1/billing/pay \
      --header 'Authorization: Bearer <token>' \
      --header 'X-Organization-Id: <org-id>' \
      --header 'Content-Type: application/json' \
      --data '{
        "method": "card",
        "amount": 0,
        "metadata": {
          "type": "mail_subscription",
          "plan": "core",
          "seats": 10,
          "billingCycle": "monthly"
        }
      }'
    ```

    ```json theme={null}
    {
      "success": true,
      "checkoutUrl": "https://checkout.paystack.com/...",
      "reference": "NI-550e8400-e29b-41d4-a716-446655440000"
    }
    ```
  </Tab>
</Tabs>

## Response fields

<ResponseField name="success" type="boolean">
  `true` on a successful request.
</ResponseField>

<ResponseField name="checkoutUrl" type="string">
  Paystack-hosted checkout URL. Present for `card` method payments.
</ResponseField>

<ResponseField name="reference" type="string">
  Unique payment reference in the format `NI-<uuid>`. Use this to reconcile the transaction.
</ResponseField>

<ResponseField name="message" type="string">
  Human-readable status message. Present for `mobile_money` and `saved_method` payments.
</ResponseField>
