← Slimpay.ng

Used by every "Try It" panel across these docs to call app.slimpay.ng for real. Get one from Authentication — register or log in, then paste the token here. Stored only in this browser (localStorage), never sent anywhere but the Slimpay API, and auto-cleared after 8 hours.

SDKs

API Client

Slimpay\School\Client calls Slimpay on behalf of your school using your API key.

php
use Slimpay\School\Client;

$slimpay = new Client(
    apiKey:  getenv('SLIMPAY_API_KEY'),                 // sandbox or live
    baseUrl: 'https://api.slimpay.ng/api/v1',          // default, shown for clarity
);
Keys decide the environment

A sandbox key hits the sandbox; a live key is real money. Keep the live key server-side only.

collectInvoice()

Start a payment for an invoice that lives in your system.

php
$checkout = $slimpay->collectInvoice(
    schoolId:    'SCH-9K2H7XQZ',
    invoiceId:   'INV-8841',
    redirectUrl: 'https://portal.example.edu.ng/payments/return',
);

return redirect($checkout->url);
  1. Slimpay validates your key and school_id.
  2. Slimpay calls your invoice lookup for the amount and student.
  3. A checkout is created and returned. The payer pays, then returns to your redirectUrl.
  4. Slimpay sends a payment.received webhook.
Don't trust the redirect

Never mark an invoice paid from the redirect alone. Wait for the webhook.

The Checkout object

PropertyMeaning
referenceCheckout reference (SCH-...); matches checkout_reference in the webhook
urlSend the payer here
invoiceIdEcho of your invoice id
amountTotal the payer pays
schoolReceives / platformFeeThe split
studentstudent_id, name, class as returned by your lookup
expiresAtISO-8601; checkouts last 30 minutes

Retrying is safe: calling collectInvoice() again for the same invoice while a checkout is unexpired returns the same checkout. redirectUrl is required and must be a valid URL.

Errors

Failures throw Slimpay\School\Exceptions\ApiException:

php
use Slimpay\School\Exceptions\ApiException;

try {
    $checkout = $slimpay->collectInvoice(...);
} catch (ApiException $e) {
    $e->getMessage();   // human-readable
    $e->httpStatus;     // 0 when Slimpay couldn't be reached
    $e->errorCode;      // machine-readable, may be null
    $e->body;           // full decoded response
}
errorCodeHTTPMeaning
SETTLEMENT_PENDING422Settlement account not approved yet
INVOICE_LOOKUP_NOT_CONFIGURED422No invoice lookup URL/secret saved
INVOICE_NOT_FOUND404Your endpoint returned not-found, timed out or answered badly
INVOICE_NOT_COLLECTIBLE422Invoice status isn't unpaid/pending/due
INVOICE_COLLECT_LOCKED409Another request for this invoice is in flight; retry shortly
(none)401Missing or invalid API key
(none)403school_id doesn't belong to this key
(none)422Validation failure, or amount under ₦100

Rate limits apply to financial endpoints; back off and retry on HTTP 429.

Custom HTTP transport

By default the client uses ext-curl. To use Guzzle, Symfony HttpClient or a test double, pass a callable returning [statusCode, rawBody]:

php
$slimpay = new Client($key, transport: function (string $method, string $url, array $headers, ?string $body): array {
    $res = $guzzle->request($method, $url, ['headers' => $headers, 'body' => $body, 'http_errors' => false]);
    return [$res->getStatusCode(), (string) $res->getBody()];
});