# Runbook — agent onboarding & approval Handling self-registered agent applications. Owner: ZFA agency management + compliance. ## Applicant types | Type | IRA licence required | Sponsor required | | --- | --- | --- | | `licensed` | Yes (attach `AgentLicense` doc). | No. | | `introducer` | No — but MUST be attached to a licensed sponsor. | Yes. | Both must submit National ID (NIN + document copy) — mandatory for KYC. ## Steps 1. **Applicant self-registers** via `POST /api/v1/agents/register`. Row lands with `kycStatus: 'pending'` and `selfRegistered: true`. No InsureLink agency number is issued yet. 2. **Compliance reviews KYC documents.** - Fetch: `GET /api/v1/agents/{id}` — expand `documents`. - Verify NIN document, licence (if licensed), sponsor letter (if introducer). - Reject: `POST /api/v1/agents/{id}/reject` with a reason. Applicant is notified via their preferred channel (email/SMS/WhatsApp). 3. **Sponsor invariant (introducers only).** The sponsor UUID or public code must resolve to an ACTIVE licensed agent. If the sponsor is inactive/suspended, applicant is auto-rejected with `SPONSOR_INVALID`. Applicant may re-submit with a different sponsor. 4. **Approve.** `POST /api/v1/agents/{id}/approve`. This: - Issues an InsureLink agency number (auto-generated `AGT-XX-XXXXXXXXXX`). - Flips `kycStatus` to `verified` and sets `kycExpiresAt` = 12 months from now (IRA re-verification cadence). - Issues a subscription record (default `SubscriptionPlan`, prorated). - Fires the welcome notification with credentials. 5. **IRA registration number** (licensed only): captured on the licence record + mirrored to `Agent.iraRegistrationNumber` so it appears on the profile. Update via `POST /api/v1/agents/{id}/licenses`. ## KYC expiry - A scheduled job flags agents with `kycExpiresAt < now + 30d` and notifies them. On expiry, `kycStatus` transitions to `expired` and the agent is blocked from creating new referrals (existing referrals / commissions are untouched). - Re-verification is a fresh document submission + compliance re-review. Use the same `/approve` endpoint after review. ## Suspend / reinstate - Suspend: `POST /api/v1/agents/{id}/suspend` — captures reason, revokes API keys, keeps historical records. - Reinstate: `POST /api/v1/agents/{id}/reinstate`. Introducers sponsored by a suspended agent are NOT auto-suspended; re-verify their sponsor invariant manually.