# Integrate NuePay API v1

Build against https://api.nuepay.net/v1. Read the linked contract and relevant guides before writing code. If behavior is unspecified, flag the gap instead of inventing an endpoint or parameter.

## Implementation rules

- Call NuePay from your server with `Authorization: Bearer <secret>`. Keep credentials in environment variables; never embed them in browser code, prompts, logs or source control.
- A named key identifies its application and merchant. Do not send an application nickname or account number for authentication. Up to ten applications share the merchant wallet; there are no separate application wallets or spending scopes.
- Start with `np_test_` credentials and simulated funds. The same API base accepts test and live keys. Verify `/application` and the expected `mode` before testing. Only switch to real payments when explicitly authorized by the merchant.
- Send UGX amounts as decimal strings, never binary floating-point calculations. Collections credit the requested principal; the payer covers the quoted total, rounded up to whole UGX. Disbursements require whole UGX amounts and debit principal plus fee. Get `/quotes` before displaying charges; quotes do not move or reserve funds.
- Persist a UUID and the exact payment payload before calling `/collections` or `/disbursements`. Send that UUID in `Idempotency-Key`. After a timeout or retry, reuse both; never issue a fresh UUID to retry an uncertain payment. A changed payload with the same UUID returns `409`.
- `202` means accepted. The payment is complete only when `status` is `success`. `process` includes pending or under-review payments; a timeout is not proof of failure. Read `/transactions/{reference}` and reconcile before fulfilling or retrying.
- Handle non-2xx responses using `code`, `message` and `errors`. Log the HTTP `X-Request-Id` for investigation; `data.request_id` identifies the original payment UUID, not the current HTTP attempt. Honor rate limits and use bounded backoff.
- Configure each application's HTTPS notification URL in API Keys. Webhook and API signing secrets are separate. Verify `X-NuePay-Signature` using HMAC-SHA256 over `timestamp + "." + raw_body`, compare in constant time, and reject timestamps more than five minutes from your synchronized clock.
- After signature verification, match body `id` to `X-NuePay-Event-Id`, check `livemode`, durably deduplicate event IDs, and apply only newer payment `version` values. Save events before returning 2xx. Deliveries may repeat or arrive out of order; fulfil a real order only on a live success.

## Acceptance checks

- Test collection and disbursement success, failure and timeout with the sandbox simulation endpoint. Sandbox never moves real funds; sandbox webhook delivery is opt-in.
- Test identical retries, changed-payload conflicts and a network timeout after dispatch. Verify that neither charges nor fulfilment repeat.
- Test invalid signatures, stale timestamps, duplicate/out-of-order webhooks, test/live isolation and insufficient wallet funds.
- Store payment reference, application ID, merchant reference, idempotency UUID, status and version. Reconcile any unresolved payment before showing a final outcome.

## Read next

- [Quickstart](https://docs.nuepay.net/quickstart/index.md)
- [All endpoints](https://docs.nuepay.net/api/index.md)
- [Retries and statuses](https://docs.nuepay.net/reliability/index.md)
- [Webhook verification](https://docs.nuepay.net/webhooks/index.md)
- [Going live](https://docs.nuepay.net/going-live/index.md)

## Source

API v1. Behavior reviewed against platform commit `4133868d96070eef6352f9fe2a1d0278bcab38f6` on 2026-10-22.
Docs index: https://docs.nuepay.net/llms.txt. Contract: https://docs.nuepay.net/openapi.json.
