Developers

API documentation

Use this API from a school website or SIS. Keep API keys on the server. Parents can also pay at the hosted portal without any integration.

Base URL

https://pay.edubetacare.online/api

Auth

Authorization: Bearer ebc_test_…

Parent portal

https://pay.edubetacare.online/s/{slug}

Quick start

  1. In Admin → Schools → Manage, create or regenerate a sandbox API key.
  2. Store the key as EDUBETACARE_API_KEY on the school server.
  3. Create a payment with POST /v1/payments or send parents to the hosted portal.
  4. Treat only SUCCESSFUL as paid. Created / pending is not money received.

Prompt for the school website

Paste this into Cursor / ChatGPT in the school website repo to wire Pay Fees.

You are integrating EduBetaCare Pay into this school website.

EduBetaCare Pay is a multi-tenant school fee payment gateway. Do not rebuild payments. Call the hosted API and send parents to the hosted checkout when needed.

## Environment
- API base: https://pay.edubetacare.online/api
- Parent checkout: https://pay.edubetacare.online/s/{SCHOOL_SLUG}
- Auth header: Authorization: Bearer {SCHOOL_API_KEY}
- API keys start with ebc_test_ (sandbox) or ebc_live_ (production)
- Amounts are integers in Naira (85000 = ₦85,000)
- Currency: NGN
- Every JSON response is: { "success": true|false, "data": ..., "error": { "code", "message" }, "request_id" }
- Mutating calls MUST send Idempotency-Key: a unique UUID per logical operation
- Content-Type: application/json

## What this school site must do
1. Store the school slug and API key in server-side env only. Never expose the API key in browser JS.
2. Keep student_id and invoice_id as the school's existing IDs. Those are the identifiers EduBetaCare uses (external_student_id / external_invoice_id).
3. When a parent should pay:
   Option A — hosted checkout (simplest): redirect or link to https://pay.edubetacare.online/s/{SCHOOL_SLUG} and let the parent enter student/invoice ID.
   Option B — API checkout from the school portal:
     a. POST https://pay.edubetacare.online/api/v1/payments with student_id, invoice_id, amount, customer, payment_method
     b. If virtual_account_temporary, show account_number, bank_name, account_name, amount, reference
     c. Poll GET https://pay.edubetacare.online/api/v1/payments/{id} or GET https://pay.edubetacare.online/api/public/payments/{reference}/status until status is SUCCESSFUL, FAILED, or EXPIRED
     d. On SUCCESSFUL, mark the invoice paid in this school system
4. Register a webhook URL (HTTPS) to receive payment.successful and payment.failed. Verify you persist the payment reference so retries are idempotent.
5. Do not treat "payment created" as paid. Only SUCCESSFUL is paid.

## Create payment
POST https://pay.edubetacare.online/api/v1/payments
Authorization: Bearer ebc_test_...
Idempotency-Key: <uuid>
{
  "payment_method": "virtual_account_temporary",
  "student_id": "STU-00123",
  "invoice_id": "INV-2026-00421",
  "amount": 85000,
  "currency": "NGN",
  "description": "2026/2027 School Fees",
  "customer": { "name": "Parent Name", "email": "parent@example.com", "phone": "08000000000" }
}

payment_method: virtual_account_temporary | virtual_account_static | card | direct_debit

## Lookup student / invoice (no API key; public)
POST https://pay.edubetacare.online/api/public/schools/{slug}/lookup
{ "student_id": "STU-00123" } or { "invoice_id": "INV-2026-00421" }

## List / get payments
GET https://pay.edubetacare.online/api/v1/payments
GET https://pay.edubetacare.online/api/v1/payments/{payment_id_or_public_id}

## Direct debit OTP
POST https://pay.edubetacare.online/api/v1/direct-debit/mandates/{reference}/validate
{ "otp": "123456" }

## Payouts (school disbursement)
POST https://pay.edubetacare.online/api/v1/payouts
{ "source_account": "...", "pin": "...", "amount": 10000, "beneficiary": { "name": "...", "account_number": "0123456789", "bank_code": "058" } }

## UI requirements
- Add a "Pay fees" button on invoice / student billing screens
- Show payment reference after initiation
- Show a pending state until webhook or poll confirms SUCCESSFUL
- Never log or commit API keys

If the codebase already has invoices and students, wire Pay fees to those records. Prefer server-side routes/controllers over client-side secret usage.

Endpoints

POST/v1/paymentsAPI key · payments:write

Example

curl -X POST https://pay.edubetacare.online/api/v1/payments \
  -H "Authorization: Bearer ebc_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "payment_method": "virtual_account_temporary",
    "student_id": "STU-00123",
    "invoice_id": "INV-2026-00421",
    "amount": 85000,
    "currency": "NGN",
    "description": "School fees",
    "customer": {
      "name": "Jane Parent",
      "email": "parent@example.com",
      "phone": "08000000000"
    }
  }'
GET/v1/paymentsAPI key · payments:read

Example

curl https://pay.edubetacare.online/api/v1/payments \
  -H "Authorization: Bearer ebc_test_YOUR_KEY"
GET/v1/payments/{id}API key · payments:read

Example

curl https://pay.edubetacare.online/api/v1/payments/pay_xxx \
  -H "Authorization: Bearer ebc_test_YOUR_KEY"
POST/v1/payoutsAPI key · payments:write

Example

curl -X POST https://pay.edubetacare.online/api/v1/payouts \
  -H "Authorization: Bearer ebc_test_YOUR_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "source_account": "0123456789",
    "pin": "1234",
    "amount": 10000,
    "currency": "NGN",
    "narration": "Vendor payout",
    "beneficiary": {
      "name": "Vendor Ltd",
      "account_number": "0123456789",
      "bank_code": "058"
    }
  }'
POST/v1/direct-debit/mandates/{reference}/validateAPI key · payments:write

Example

curl -X POST https://pay.edubetacare.online/api/v1/direct-debit/mandates/REF/validate \
  -H "Authorization: Bearer ebc_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"otp":"123456"}'
POST/public/schools/{slug}/lookupPublic

Example

curl -X POST https://pay.edubetacare.online/api/public/schools/rising-hope/lookup \
  -H "Content-Type: application/json" \
  -d '{"student_id":"STU-00123"}'
POST/public/schools/{slug}/paymentsPublic

Example

curl -X POST https://pay.edubetacare.online/api/public/schools/rising-hope/payments \
  -H "Content-Type: application/json" \
  -d '{
    "student_id": "STU-00123",
    "invoice_id": "INV-2026-00421",
    "payment_method": "virtual_account_temporary"
  }'
GET/public/payments/{reference}/statusPublic

Example

curl https://pay.edubetacare.online/api/public/payments/EBC-XXXX/status

Payment statuses

CREATED → PENDING → PROCESSING → SUCCESSFUL. Failures: FAILED, EXPIRED, CANCELLED. Refunds: REFUNDED, PARTIALLY_REFUNDED, REVERSED.

Error envelope

JSON

{
  "success": false,
  "error": { "code": "INVALID_AMOUNT", "message": "The payment amount is invalid." },
  "request_id": "req_..."
}