Producer Onboarding
Producer onboarding in OpenInsure covers the full lifecycle from initial record creation through licensing verification, carrier appointments, E&O coverage validation, and ongoing compliance monitoring. The API is implemented in apps/api/src/routes/producer.ts with 18 endpoints under /v1/producers.
Onboarding Journey
1. Create producer record (POST /v1/producers)
│
├── OFAC / sanctions screening (automatic)
│ ├── pass → continue
│ ├── review → flagged for manual review
│ └── block → onboarding rejected (403)
│
2. Add state licenses (POST /v1/producers/:id/licenses)
│
3. Verify via NIPR lookup (POST /v1/producers/:id/nipr-lookup)
│
4. Upload E&O coverage (POST /v1/producers/:id/eo-coverage)
│
5. Create carrier appointments (POST /v1/producers/:id/appointments)
│
6. KYB verification via Persona (POST /v1/producers/:id/kyb-session)
│
7. Activate producer (PATCH /v1/producers/:id/status → active)
Producer Types
The system supports four producer types, each with different onboarding requirements:
| Type | Description | Typical NPN Source |
|---|---|---|
individual | Licensed individual agent | Personal NPN |
agency | Retail insurance agency | Agency NPN |
mga | Managing General Agent | Entity NPN |
wholesaler | Surplus lines wholesaler/broker | Entity NPN |
Creating a Producer
POST /v1/producers
Authorization: Bearer <token>
Content-Type: application/json
{
"orgId": "org_01J8...",
"type": "agency",
"legalName": "Acme Insurance Agency LLC",
"dba": "Acme Insurance",
"ein": "12-3456789",
"npn": "12345678",
"email": "admin@acmeagency.com",
"phone": "555-123-4567",
"parentProducerId": "prod_01J8...",
"commissionScheduleId": "cs_01J8..."
}
Required fields: orgId, type, legalName, npn, email. Optional fields allow linking to a parent producer (for hierarchy) and a commission schedule.
Sanctions Screening
Every new producer is automatically screened against OFAC and international sanctions lists during creation. The screening uses the @openinsure/compliance module:
- Allowlist check -- If the entity is pre-approved in the
sanctionsAllowlisttable, screening is skipped and the audit log records apasswithbackend: static. - OFAC screening -- For non-allowlisted entities, the system calls the OpenSanctions API with the producer's legal name.
- Decision resolution -- The
resolveDecision()function maps the screening result to one of three tiers:
| Decision | Behavior |
|---|---|
pass | Producer created normally |
review | Producer created with sanctionsReviewPending: true. A compliance.sanctions_review event is queued for manual review. |
block | Producer creation rejected with HTTP 403. Response includes match details (entry ID, match type, score, sanction programs). |
Every screening result is written to the sanctionsAuditLog table with source (producer_onboarding), actor user ID, and the matched entity details.
State Licensing
Adding Licenses
POST /v1/producers/:id/licenses
Authorization: Bearer <token>
Content-Type: application/json
{
"orgId": "org_01J8...",
"state": "FL",
"licenseNumber": "P123456",
"licenseType": "property_casualty",
"effectiveDate": "2025-01-01",
"expirationDate": "2027-01-01",
"linesOfAuthority": ["commercial_auto", "general_liability"],
"continuingEducationDue": "2026-06-30"
}
License Types
| Type | Description |
|---|---|
property_casualty | P&C lines (most common for MGA producers) |
life_health | Life and health insurance |
surplus_lines | Non-admitted / surplus lines broker license |
adjuster | Claims adjuster license |
consultant | Insurance consultant |
License Status Tracking
Licenses move through the following statuses:
| Status | Description |
|---|---|
active | Currently valid |
pending | Applied for, not yet issued |
expired | Past expiration date |
suspended | Temporarily suspended by the DOI |
revoked | Permanently revoked |
Expiring License Alerts
The system proactively surfaces licenses approaching expiration:
GET /v1/producers/:id/licenses/expiring?days=90
Authorization: Bearer <token>
Returns all licenses for the producer that expire within the specified window (default 90 days), sorted by expiration date ascending. The response includes a cutoff timestamp for reference.
NIPR Integration
The National Insurance Producer Registry (NIPR) integration verifies producer license data against the authoritative national database.
POST /v1/producers/:id/nipr-lookup
Authorization: Bearer <token>
The endpoint:
- Loads the producer record to retrieve the NPN (National Producer Number).
- Calls the NIPR API via
NiprProviderfrom@openinsure/integrations. - Returns the NIPR verification result, which includes license status, appointments, and state-level details across all jurisdictions.
Requires org_admin, compliance, or underwriter role. The NIPR API key is configured via the NIPR_API_KEY environment variable.
NIPR lookup results are returned as-is from the NIPR API. The system does not automatically update license records based on NIPR data -- that is a manual step to allow the compliance team to review discrepancies.
E&O Coverage Verification
Errors & Omissions insurance is required for all producing agents. The platform tracks E&O coverage records per producer.
Listing E&O Coverage
GET /v1/producers/:id/eo-coverage
Authorization: Bearer <token>
Adding E&O Coverage
POST /v1/producers/:id/eo-coverage
Authorization: Bearer <token>
Content-Type: application/json
{
"orgId": "org_01J8...",
"carrierName": "Swiss Re Corporate Solutions",
"policyNumber": "EO-2025-789",
"coverageLimit": 1000000,
"effectiveDate": "2025-01-01",
"expirationDate": "2026-01-01"
}
Requires org_admin or compliance role. The coverageLimit is stored as a dollar amount. E&O records are stored in the producer_eo_coverage table.
Carrier Appointments
Appointments represent the contractual relationship between a producer and a carrier, authorizing the producer to sell policies on behalf of the carrier.
Creating an Appointment
POST /v1/producers/:id/appointments
Authorization: Bearer <token>
Content-Type: application/json
{
"orgId": "org_01J8...",
"carrierId": "carrier_01J8...",
"carrierName": "National General Insurance",
"effectiveDate": "2025-01-01",
"terminationDate": "2026-12-31",
"linesOfBusiness": ["commercial_auto", "general_liability"],
"states": ["FL", "TX", "GA"]
}
Appointment Status Lifecycle
| Status | Description |
|---|---|
active | Currently authorized to sell |
pending | Appointment requested, awaiting carrier confirmation |
suspended | Temporarily suspended (compliance issue or carrier action) |
terminated | Permanently ended |
Update status via:
PATCH /v1/producers/:id/appointments/:apptId
Authorization: Bearer <token>
Content-Type: application/json
{
"status": "terminated",
"terminationDate": "2026-03-01"
}
Authority Validation
Before a producer can bind a policy, the system verifies they have proper authority for the state and line of business:
GET /v1/producers/:id/authority-check?state=FL&lob=commercial_auto
Authorization: Bearer <token>
The authority check verifies two conditions simultaneously:
- Active state license -- The producer holds an active license in the requested state.
- Active carrier appointment -- The producer has an active appointment with a carrier that covers the requested line of business and state.
The response includes:
{
"authorized": true,
"state": "FL",
"lob": "commercial_auto",
"license": {
"id": "lic_01J8...",
"licenseNumber": "P123456",
"status": "active",
"expirationDate": "2027-01-01",
"isExpiringSoon": false
},
"appointment": {
"id": "appt_01J8...",
"carrierId": "carrier_01J8...",
"carrierName": "National General Insurance",
"status": "active"
}
}
The isExpiringSoon flag is set when the license expires within 90 days.
KYB Verification (Persona)
For agencies and MGAs, OpenInsure supports Know Your Business (KYB) verification through Persona:
POST /v1/producers/:id/kyb-session
Authorization: Bearer <token>
The endpoint creates a Persona inquiry using the producer's legal name and email, returning a sessionToken for the embedded verification flow. Requires the PERSONA_API_KEY and PERSONA_TEMPLATE_ID environment variables.
Producer Hierarchy
Producers can be organized in a parent-child hierarchy (e.g., an MGA with sub-agencies, or an agency with individual agents):
GET /v1/producers/:id/downline
Authorization: Bearer <token>
Returns the direct downline (children) of a producer, sourced from the producer_hierarchies table. This is used for commission roll-up calculations and management reporting.
Operations Dashboard
The operations endpoint aggregates work queue data for a producer across compliance, commissions, and underwriting:
GET /v1/producers/:id/operations?days=30
Authorization: Bearer <token>
Response:
| Section | Source | Description |
|---|---|---|
expiringLicenses | producerLicenses | Active licenses expiring within the window |
pendingCommissions | commissionEntries | Commissions in calculated or approved status |
exceptionSubmissions | submissions | Submissions in referred or declined status |
Updating Producer Records
Producers can update their own email, phone, and DBA. Admins can update all mutable fields including legal name, type, and commission schedule:
PUT /v1/producers/:id
Authorization: Bearer <token>
Content-Type: application/json
{
"legalName": "Acme Insurance Group LLC",
"email": "admin@acmegroup.com",
"commissionScheduleId": "cs_01J8..."
}
Producer Status Lifecycle
| Status | Description |
|---|---|
active | Authorized to transact business |
inactive | Temporarily not transacting (voluntary) |
suspended | Suspended for compliance or disciplinary reasons |
terminated | Permanently terminated |
Status transitions require the org_admin role:
PATCH /v1/producers/:id/status
Authorization: Bearer <token>
Content-Type: application/json
{
"status": "suspended",
"reason": "Pending E&O renewal"
}
Authorization Summary
| Endpoint | Allowed Roles |
|---|---|
| List / get producers | org_admin, superadmin, underwriter |
| Create / update producer | org_admin (create), org_admin or producer (update) |
| Status transitions | org_admin |
| Licenses (read) | org_admin, superadmin, underwriter, compliance, producer |
| Licenses (write) | org_admin, compliance |
| Appointments (read) | org_admin, superadmin, underwriter, producer |
| Appointments (write) | org_admin |
| Authority check | org_admin, superadmin, underwriter |
| NIPR lookup | org_admin, compliance, underwriter |
| E&O coverage (read) | org_admin, superadmin, underwriter, compliance, producer |
| E&O coverage (write) | org_admin, compliance |
| KYB session | org_admin |
| Downline hierarchy | org_admin, superadmin |
| Operations dashboard | org_admin, superadmin, underwriter, compliance |