Your first payment.
Create a sandbox key, send one request, and confirm a simulated mobile money collection.
1. Get your sandbox key
Sign in to the NuePay dashboard. Create a named key for your application, select Sandbox Key, validate your transactional PIN, then copy the np_test_ secret.
API key access currently requires an active, approved business account with API access enabled. Your secret stays on your server.
export NUEPAY_TEST_KEY="YOUR_SANDBOX_SECRET"
# Generate once per payment. Save this UUID before sending.
export PAYMENT_UUID="$(node -e 'console.log(crypto.randomUUID())')"2. Create a collection
Here, 500.00 is the wallet credit, not the total phone charge. Fees are added. Always send amounts as decimal strings.
curl https://api.nuepay.net/v1/collections \
-H "Authorization: Bearer $NUEPAY_TEST_KEY" \
-H "Idempotency-Key: $PAYMENT_UUID" \
-H 'Content-Type: application/json' \
-d '{
"amount": "500.00",
"currency": "UGX",
"phone": "0772000000",
"merchant_reference": "order-123"
}'// Persist this UUID with your order; reuse it when retrying.
const response = await fetch('https://api.nuepay.net/v1/collections', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.NUEPAY_TEST_KEY}`,
'Idempotency-Key': paymentUuid,
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: '500.00', currency: 'UGX',
phone: '0772000000', merchant_reference: 'order-123',
}),
});
const result = await response.json();
if (!response.ok) throw new Error(result.message);
console.log(result.data);$curl = curl_init('https://api.nuepay.net/v1/collections');
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer '.getenv('NUEPAY_TEST_KEY'),
'Idempotency-Key: '.$paymentUuid, // Reuse for retries.
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => '500.00', 'currency' => 'UGX',
'phone' => '0772000000', 'merchant_reference' => 'order-123',
]),
]);
$body = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
if ($body === false || $status < 200 || $status >= 300) {
throw new RuntimeException('Inspect the error and retry safely.');
}
$result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);import json, os, urllib.request
request = urllib.request.Request(
'https://api.nuepay.net/v1/collections',
method='POST',
headers={
'Authorization': 'Bearer ' + os.environ['NUEPAY_TEST_KEY'],
'Idempotency-Key': payment_uuid, # Reuse for retries.
'Content-Type': 'application/json',
},
data=json.dumps({
'amount': '500.00', 'currency': 'UGX',
'phone': '0772000000', 'merchant_reference': 'order-123',
}).encode(),
)
with urllib.request.urlopen(request, timeout=30) as response:
result = json.load(response)
print(result['data'])3. Confirm the simulated outcome
Copy data.reference from the creation response and use it below. This endpoint accepts test keys only.
curl https://api.nuepay.net/v1/sandbox/transactions/YOUR_REFERENCE/simulate \
-H "Authorization: Bearer $NUEPAY_TEST_KEY" \
-H 'Content-Type: application/json' \
-d '{"outcome":"success"}'The payment now reports success, and its principal credits your simulated wallet exactly once. No phone prompt, real wallet movement or Yo request occurs.
Then test the rest of the journey
Try failed and timeout, configure a webhook receiver, and use quotes to show the correct charge. The authenticated sandbox playground can run these requests for you.
If you import Postman, set secret_key to your test secret, choose a UUID for idempotency_key, and copy the response reference to reference.

