Quickstart
You'll go from zero to your first API call in about five minutes.
Base URL (production): https://api.insurelink.vitalplatforms.com
Auth: JWT bearer token, obtained via POST /api/v1/auth/login.
Content type: application/json everywhere unless noted.
1. Log in
Every non-Public endpoint requires an access token. The bootstrap admin
credentials are seeded on install — rotate them immediately in production.
curl -sSX POST https://api.insurelink.vitalplatforms.com/api/v1/auth/login \
-H 'content-type: application/json' \
-d '{"email":"admin@insurelink.local","password":"ChangeMe!Insur3Link2026"}'
The response gives you:
{
"data": {
"accessToken": "eyJ...",
"refreshToken": "familyId.opaquetoken",
"expiresIn": 900,
"refreshExpiresIn": 2592000
},
"meta": { "requestId": "req_..." }
}
Store accessToken and send it on every subsequent request:
Authorization: Bearer eyJ...
2. Rotate the bootstrap password
The admin bootstrap password must be replaced before you go live.
curl -sSX POST https://api.insurelink.vitalplatforms.com/api/v1/auth/change-password \
-H "authorization: Bearer $ACCESS" \
-H 'content-type: application/json' \
-d '{"currentPassword":"ChangeMe!Insur3Link2026","newPassword":"<something-strong>"}'
3. Enable MFA (recommended)
Every admin should carry MFA. The setup call returns a TOTP otpauth:// URI
and a QR-code data URI ready to scan.
# 3.1 Setup — returns qrCode + otpauth
curl -sSX POST https://api.insurelink.vitalplatforms.com/api/v1/auth/mfa/setup \
-H "authorization: Bearer $ACCESS"
# 3.2 Verify with the 6-digit code from your authenticator app
curl -sSX POST https://api.insurelink.vitalplatforms.com/api/v1/auth/mfa/verify \
-H "authorization: Bearer $ACCESS" \
-H 'content-type: application/json' \
-d '{"token":"123456"}'
For passkey-based (WebAuthn) MFA, see the Passkeys API reference and the Passkeys review doc.
4. Onboard a real agent
The platform is pre-loaded with the 2,594-agent IRA of Uganda register. When a new agent registers, the system verifies their IRA number and pre-fills their licence data — you review the KYC pack and approve.
# 4.1 Verify an IRA number (public endpoint, no auth needed)
curl -sS "https://api.insurelink.vitalplatforms.com/api/v1/public/ira-registry/IRA%2FIA%2F1652%2F2016"
# 4.2 Self-register (agent-side flow)
curl -sSX POST https://api.insurelink.vitalplatforms.com/api/v1/agents/register \
-H 'content-type: application/json' \
-d '{
"iraRegistrationNumber": "IRA/IA/1652/2016",
"nationalId": "CM12345678901X",
"email": "agent@example.ug",
"phone": "+256701123456"
}'
5. Create a referral
Referrals are what the platform is built to move.
curl -sSX POST https://api.insurelink.vitalplatforms.com/api/v1/referrals \
-H "authorization: Bearer $ACCESS" \
-H 'content-type: application/json' \
-d '{
"insurerId": "550e8400-...",
"insurerProductId": "550e8400-...",
"clientFirstName": "Ada",
"clientLastName": "Lovelace",
"clientPhone": "+256701555001",
"requestedCoverage": 5000000,
"currency": "UGX"
}'
Once approved through its workflow, the referral produces a Commission
record. Approving the commission credits the agent wallet net of every
active fee, tax, and levy in /deduction-types.
6. Configure fees, taxes and deductions
Every deduction is ZFA-configurable. Seeded defaults: 5% ZFA fee, 6% URA withholding tax, UGX 500 IIU membership contribution (min gross UGX 10,000). Rules cascade in priority order — a tax after a fee taxes the post-fee value.
# List the current schedule
curl -sS "https://api.insurelink.vitalplatforms.com/api/v1/deduction-types?scope=commission" \
-H "authorization: Bearer $ACCESS"
# Preview a specific gross amount
curl -sSX POST https://api.insurelink.vitalplatforms.com/api/v1/deduction-types/preview \
-H "authorization: Bearer $ACCESS" \
-H 'content-type: application/json' \
-d '{"scope":"commission","grossAmount":100000,"currency":"UGX"}'
Where to go next
- Explore every endpoint: the complete matrix shows every route with its public/restricted access and required permission.
- Deep-dive a controller: the API Reference has one page per controller with schemas + Try-It panels.
- Learn the ops flows: runbooks cover incident response, key rotation, insurer/agent onboarding, dispute review.
Response envelope
Every successful response has this shape:
{
"data": { "...": "the resource" },
"meta": {
"requestId": "req_<uuid>",
"pagination": { "page": 1, "pageSize": 20, "total": 42 }
}
}
Errors:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request is invalid.",
"details": [{ "field": "email", "message": "must be an email" }]
}
}
Rate limits
Public endpoints are rate-limited per client IP (5–30/min depending on the
route). Authenticated endpoints follow per-user throttling; partner API keys
carry a per-key rate limit set at issue time.
Idempotency
The following endpoints accept an Idempotency-Key header and dedupe replays
inside a 24-hour window:
POST /referralsPOST /wallet/withdrawPOST /payment-batchesPOST /webhooks/insurers/:code
Authorization model in one paragraph
Permissions are a hardcoded catalogue in src/common/security/roles.ts —
251 literals like wallet:read, commission:approve, self:passkey:manage.
Roles are database rows that map to any subset of the catalogue. Every one
of the 380 endpoints declares its guard via @RequirePermissions,
@RequireAnyPermission, @RequireRoles, @Public, or @ClientSessionOnly;
a build-time lint fails CI if any handler is unguarded. Object-level
scoping is layered on top so agents automatically see only their own
referrals, commissions, wallet, and investments.
The three access tiers
The endpoint matrix labels every route as one of:
| Tier | What it means | Auth header |
|---|---|---|
| 🌐 Public | No credential required. Rate-limited at the edge. Used for OTP request/verify, IRA registry lookup, health probes. | none |
| 🎟️ Client session | Bypasses the platform JWT guard but the handler validates a ClientPortalSession bearer token minted by POST /client-portal/otp/verify. Only the /client-portal/me/* endpoints use this tier. | Authorization: Bearer <sessionToken> |
| 🔒 Restricted | Requires a platform JWT (POST /auth/login) plus the specific permission or role declared on the handler. | Authorization: Bearer <accessToken> |
A route that is marked Client session in the matrix is not safe to hit
unauthenticated — its @Public() decorator only disables the platform JWT
guard; the handler itself rejects the request unless it can resolve a valid
portal session issued after OTP verification.