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

# Accept payments through the API

> Create payment intents, test completion in sandbox, and reconcile the resulting business treasury credit.

A payment intent represents one amount owed to your business. It carries your order reference, accepted payment method, settlement preference, customer context, expiry, and payment lifecycle state.

Use a server-side API key with `payment_intents:read`, `payment_intents:write`, and `treasury:read`.

<Warning>
  Direct stablecoin collection to a unique payment-intent address is not yet certified for live use. Deposit monitoring, confirmation, treasury crediting, and sweeping must be enabled by NorthFond before you display such an address to a real customer. Use sandbox for this flow until NorthFond confirms live readiness for your business.
</Warning>

## Sandbox end-to-end example

<Steps>
  <Step title="Create a payment intent">
    Use a durable order identifier as `external_reference`. Send the same idempotency key when retrying this exact request.

    ```bash theme={null}
    IDEMPOTENCY_KEY="payment-order-1042"

    curl --fail-with-body --silent --show-error \
      --request POST \
      --url https://payment.gideondevrel.xyz/api/v1/business/payment-intents \
      --header "Authorization: Bearer $NORTHFOND_API_KEY" \
      --header "Content-Type: application/json" \
      --header "Idempotency-Key: $IDEMPOTENCY_KEY" \
      --data '{
        "external_reference": "order_1042",
        "amount": { "currency": "KES", "value": "100" },
        "accepted_payment_methods": ["mobile_money"],
        "settlement": { "mode": "stablecoin", "asset": "USDC", "chain": "base" },
        "customer": {
          "reference": "student_88",
          "email": "student@example.com",
          "name": "Example Student"
        },
        "metadata": { "course_id": "course_12" },
        "expires_in_seconds": 1800
      }'
    ```
  </Step>

  <Step title="Complete the sandbox payment">
    Simulation is accepted only by sandbox credentials and never moves funds.

    ```bash theme={null}
    PAYMENT_INTENT_ID="replace_with_payment_intent_id"

    curl --fail-with-body --silent --show-error \
      --request POST \
      --url "https://payment.gideondevrel.xyz/api/v1/business/payment-intents/$PAYMENT_INTENT_ID/simulate" \
      --header "Authorization: Bearer $NORTHFOND_API_KEY" \
      --header "Content-Type: application/json" \
      --header "Idempotency-Key: simulate-order-1042" \
      --data '{ "payment_method": "mobile_money" }'
    ```
  </Step>

  <Step title="Verify the payment">
    Retrieve the intent and require `status` to equal `completed` before granting access to the purchased resource.

    ```bash theme={null}
    curl --fail-with-body --silent --show-error \
      --url "https://payment.gideondevrel.xyz/api/v1/business/payment-intents/$PAYMENT_INTENT_ID" \
      --header "Authorization: Bearer $NORTHFOND_API_KEY"
    ```
  </Step>

  <Step title="Reconcile the treasury">
    Confirm that the payment appears in deposits and that the treasury balance reflects the completed settlement.

    ```bash theme={null}
    curl --fail-with-body --silent --show-error \
      --url "https://payment.gideondevrel.xyz/api/v1/business/treasury/deposits?limit=25" \
      --header "Authorization: Bearer $NORTHFOND_API_KEY"

    curl --fail-with-body --silent --show-error \
      --url https://payment.gideondevrel.xyz/api/v1/business/treasury/balances \
      --header "Authorization: Bearer $NORTHFOND_API_KEY"
    ```
  </Step>
</Steps>

## Production collection

For the current controlled beta, use a NorthFond-hosted [payment link](/payment-links) for live mobile-money collection. The hosted checkout gathers the customer phone and network, starts the provider request, and updates the underlying payment intent.

Do not fulfill from a checkout redirect, `awaiting_payment`, `approved`, or `processing`. Fulfill only after a signed `payment_intent.completed` webhook, then retrieve the payment intent and reconcile its treasury deposit using your own durable `external_reference`.

## Status handling

| Status                           | Integration action                                  |
| -------------------------------- | --------------------------------------------------- |
| `awaiting_payment`               | Show payment instructions or wait for the customer  |
| `funds_detected`                 | Keep the order pending while payment is confirmed   |
| `processing`                     | Keep the order pending                              |
| `review_required`                | Pause fulfillment and wait for an operator decision |
| `approved`                       | Ask the customer to resume; approval is not payment |
| `completed`                      | Reconcile and fulfill exactly once                  |
| `failed`, `cancelled`, `expired` | Do not fulfill                                      |

See [Webhooks](/webhooks), [Idempotency](/idempotency), and [Operational readiness](/operational-readiness) before enabling live traffic.
