MediLoan SDK
Let a patient finance their care at the point of treatment. Your system starts the application, MyItura underwrites it and runs the loan, and you get told what happened.
How it fits together
- Your system calls
POST /sdk/loans/initiatewith the patient and the amount being financed. - You get back an
applicationUrl. Send the patient there, or open it in a webview. - The patient completes the application, KYC and the offer on MyItura's hosted pages.
- You receive webhooks as the loan moves through its lifecycle.
MediLoan is MyItura lending to your patient. If you are the lender and want to underwrite on your own book, that is the Lending API, which uses the same key pair and a different surface.
Initiate a loan
The first step: your organisation tells us a patient wants to finance a treatment. The response carries the URL the patient completes the application at.
Body
| Field | Description |
|---|---|
| clientReferencerequiredstring | Your unique identifier for this initiation. |
| invoiceReferencestring | The invoice being funded. May repeat across initiations. |
| firstNamerequiredstring | First name of the patient. |
| phoneNumberrequiredstring | Accepted as 080..., 234... or +234.... |
| treatmentrequiredstring | What is being financed. |
| treatmentAmountrequirednumber | The amount, in kobo. 4500000 is NGN 45,000.00. |
Sending naira here finances a hundredth of the treatment, and nothing in the response will tell you so. Multiply by 100 before you send.
curl -X POST https://api.myitura.com/api/v1/sdk/loans/initiate \
-H "x-api-public-key: pk_live_abc123def456" \
-H "x-api-secret-key: sk_live_xyz789uvw012" \
-H "Content-Type: application/json" \
-d '{
"clientReference": "HOSP-001",
"invoiceReference": "INV-2025-001",
"firstName": "John",
"phoneNumber": "08012345678",
"treatment": "Surgery",
"treatmentAmount": 500000
}'{
"status": 201,
"message": "Loan initiation successful",
"data": {
"sdkReference": "AB12CD34EF",
"clientReference": "HOSP-001",
"applicationUrl": "https://loans.myitura.com/apply?sdkref=AB12CD34EF",
"status": "initiated",
"expiresAt": "2025-11-02T10:00:00.000Z"
}
}What happens next
Initiation hands you an applicationUrl and hands the patient to us. Everything between that link and the money reaching you happens on MyItura, and you follow it through webhooks rather than by calling us.
The steps the patient completes
They verify their identity, we run the checks against the bureau, the loan is decisioned and priced, and they accept the offer. None of this is yours to collect or verify. We are the lender on a MediLoan application, so the identity and affordability work is ours.
The direct debit
Before any money moves, the patient authorises a direct debit against their bank account. That authorisation happens on the payment provider's own page, so nobody, us included, ever handles their bank credentials.
A loan is not disbursed until the direct debit is confirmed live by the provider, which is a separate event from the patient finishing the authorisation form and can lag it. A loan sitting accepted but not yet disbursed is usually waiting on exactly this.
Then you are paid
On disbursement the funds settle to your organisation and you receive loan.disbursed. That is the event to reconcile against, not loan.approved: approval is a decision, disbursement is the money.
you POST /sdk/loans/initiate
-> applicationUrl, sdkReference
(you send the patient the link, or we SMS it)
patient identity and bureau checks <- we run these
offer issued and accepted
authorises the direct debit
mandate confirmed live <- gates disbursement
you <- loan.approved (decision made)
<- loan.disbursed (money settled to you)Set up the direct debit
Repayment is collected by direct debit, and a loan is not disbursed until the mandate is live. A borrower who applied through your system has never signed in here, so there is no session for them to set one up in. This is the route that does it for them.
What comes back is an authorisation URL, not an active mandate. Send your borrower to it and they authorise at their bank. A mandate nobody authorised is not permission to take money, so a link is the honest answer.
Body
Optional. Send it only when the loan has no account to debit, which happens when the profile behind it was completed without bank details. Omit it and we use what the loan already has.
| Field | Description |
|---|---|
| bankCodestring | The bank to debit. Required if you send accountNumber. |
| accountNumberstring | The account to debit. Required if you send bankCode. |
| accountNamestring | Name on the account. |
| bankNamestring | Display name of the bank. |
Checking on it
GET /sdk/loans/{loanId}/mandate returns where the borrower has got to, for polling rather than listening. The mandate events reach your webhook either way.
Tenancy is the organisation that originated the loan. A loan belonging to another partner is a 404 rather than a 403, because a 403 would confirm it exists.
curl -X POST https://api.myitura.com/api/v1/sdk/loans/$LOAN_ID/mandate \
-H "X-API-Public-Key: $MYITURA_PUBLIC_KEY" \
-H "X-API-Secret-Key: $MYITURA_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"bankCode": "058",
"accountNumber": "0123456789",
"accountName": "Adaeze Okafor",
"bankName": "Guaranty Trust Bank"
}'Events and signatures
We call your endpoint as the loan moves. Every request carries the event name and a signature over the body.
| Header | Description |
|---|---|
| X-MyItura-Event | The event name, for example loan.initiated. |
| X-MyItura-Signature | HMAC-SHA256 of the request body, keyed with your secret key. |
Events
Compute the signature over the raw body and compare in constant time. An endpoint that trusts the payload without checking is an endpoint anyone can drive.
// Signature verification is a server-side process{
"event": "loan.initiated",
"timestamp": "2024-01-08T14:30:00Z",
"data": {
"sdkReference": "SDK-A1B2C3D4",
"clientReference": "YOUR_SYSTEM_REF_123",
"invoiceReference": "INV-001",
"status": "pending",
"amount": 5000000,
"currency": "NGN",
"applicant": {
"firstName": "John",
"lastName": "Doe",
"gender": "male"
},
"applicationUrl": "https://loans.myitura.com/apply?sdkref=SDK-A1B2C3D4"
}
}Replay a missed event
Deliveries are queued and retried with a backoff, so an endpoint that is briefly unreachable does not lose anything. When yours is down for longer than the retries last, this is how you find what you missed rather than reconciling blind.
It returns your organisation's deliveries, newest first, each with its status and its last error. Pass limit to change how many come back: 1 to 200, and 100 if you do not.
Sending one again
POST /sdk/events/{id}/redeliver queues that delivery again, to the endpoint you have configured now rather than the one you had then.
The body and the event name are the ones we first sent, so a replayed event can describe a loan that has moved on since. Key your handler on the loan and make it repeatable, rather than on the order things arrived.
curl "https://api.myitura.com/api/v1/sdk/events?limit=50" \
-H "X-API-Public-Key: $MYITURA_PUBLIC_KEY" \
-H "X-API-Secret-Key: $MYITURA_SECRET_KEY"
curl -X POST https://api.myitura.com/api/v1/sdk/events/$DELIVERY_ID/redeliver \
-H "X-API-Public-Key: $MYITURA_PUBLIC_KEY" \
-H "X-API-Secret-Key: $MYITURA_SECRET_KEY"