Payments

Initialize and verify Paystack enrollment payments via the REST API.

Initialize a payment

Create a new Paystack payment session and get a checkout URL to redirect the student to.

POST /api/payments/initialize

Warning

Rate limit: 10 requests / minute per tenant. This limit is intentionally tight to prevent fraud probing. Exceeding it returns HTTP 429 with a Retry-After header. See Rate limits for retry guidance.

Headers

HeaderRequiredValue
x-api-keyYesYour tenant API key
Content-TypeYesapplication/json

Body

{
  "email": "[email protected]",
  "amount": 15000,
  "studentId": "stu_001",
  "metadata": {
    "studentName": "Amara Obi",
    "term": "Second Term 2026"
  }
}
FieldTypeRequiredDescription
emailstringYesStudent/payer email
amountnumberYesAmount in kobo (NGN × 100)
studentIdstringNoYour internal student ID
metadataobjectNoArbitrary key-value pairs echoed back on the webhook

Response 200 OK

{
  "status": true,
  "message": "Authorization URL created",
  "data": {
    "authorization_url": "https://checkout.paystack.com/abc123",
    "access_code": "abc123",
    "reference": "nxa_ref_xyz789"
  }
}

Redirect the student to authorization_url to complete payment.

Example (cURL)

curl -X POST https://nexa-ed.com/api/payments/initialize \
  -H "x-api-key: nxa_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "amount": 15000
  }'

Example (Python)

import requests
 
resp = requests.post(
    "https://nexa-ed.com/api/payments/initialize",
    headers={"x-api-key": "nxa_live_..."},
    json={"email": "[email protected]", "amount": 15000},
)
checkout_url = resp.json()["data"]["authorization_url"]

Verify a payment

Check whether a payment was successful by reference.

GET /api/payments/verify?reference=nxa_ref_xyz789

Headers

HeaderRequiredValue
x-api-keyYesYour tenant API key

Response 200 OK

{
  "status": true,
  "data": {
    "reference": "nxa_ref_xyz789",
    "status": "success",
    "amount": 15000,
    "currency": "NGN",
    "customerEmail": "[email protected]",
    "paidAt": "2026-03-15T10:22:00Z"
  }
}

status values: "success" | "failed" | "abandoned" | "pending"


Get payment config

Retrieve the tenant's payment configuration — public key, surcharge settings, and branding.

GET /api/payments/config

Headers

HeaderRequiredValue
x-api-keyYesYour tenant API key

Response 200 OK

{
  "paystackPublicKey": "pk_live_...",
  "currency": "NGN",
  "surchargePercent": 1.5,
  "surchargeFlat": 100,
  "surchargeCapKobo": 200000,
  "brandName": "Loretto College",
  "brandColor": "#10b981"
}

Get payment status

Lightweight status check — no full Paystack round-trip. Result may be cached for up to 60 seconds; use Verify a payment for authoritative results.

GET /api/payments/status?reference=nxa_ref_xyz789

Headers

HeaderRequiredValue
x-api-keyYesYour tenant API key

Response 200 OK

{
  "reference": "nxa_ref_xyz789",
  "status": "success"
}

List transactions

GET /api/payments/transactions

Headers

HeaderRequiredValue
x-api-keyYesYour tenant API key

Query params

ParamTypeDefaultDescription
limitnumber20Max results
offsetnumber0Pagination offset
statusstring—Filter by status

Response 200 OK

{
  "transactions": [
    {
      "reference": "nxa_ref_xyz789",
      "amount": 15000,
      "status": "success",
      "customerEmail": "[email protected]",
      "paidAt": "2026-03-15T10:22:00Z"
    }
  ],
  "total": 1
}

Get payment stats

Aggregated revenue and count metrics.

GET /api/payments/stats

Headers

HeaderRequiredValue
x-api-keyYesYour tenant API key

Response 200 OK

{
  "totalRevenue": 4500000,
  "totalTransactions": 300,
  "successfulTransactions": 287,
  "failedTransactions": 13,
  "currency": "NGN"
}

Webhook — payment completed

Nexa forwards a POST to your webhook URL when a payment is confirmed.

Payload

{
  "event": "payment.completed",
  "reference": "nxa_ref_xyz789",
  "amount": 15000,
  "currency": "NGN",
  "customerEmail": "[email protected]",
  "tenantId": "loretto_00123",
  "metadata": { "studentName": "Amara Obi" },
  "timestamp": 1742000000
}

Warning

customerEmail and any fields you pass via metadata may contain personally identifiable information (PII). Store and handle this data in accordance with your privacy policy and applicable data-protection regulations.

See REST API Overview → Webhook verification for signature verification.

On this page