-
Notifications
You must be signed in to change notification settings - Fork 0
Appointment events
This document provides comprehensive documentation for webhook events related to license appointments in the ProducerFlow system. Appointment webhooks deliver real-time notifications when appointment statuses change due to processing by NIPR (National Insurance Producer Registry) or direct actions by the tenant admin in Producerflow's portal.
⚕️ For appointment health and compliance monitoring, including operational status tracking and risk management, see: Appointment Operational Status
ProducerFlow supports two types of carrier integrations for license appointments:
For carriers that use NIPR (National Insurance Producer Registry), appointments follow an asynchronous workflow:
- Request Submitted: An appointment request or termination is submitted via the API
-
Initial Response: The API returns immediately with
in_progressstatus if accepted by NIPR - NIPR Processing: NIPR processes the request asynchronously (can take minutes to hours)
- Webhook Notification: When NIPR completes processing, ProducerFlow sends a webhook with the final result
- Status Updated: Subsequent API calls return the updated appointment status
For carriers that use ProducerFlow's direct appointment system, the process is immediate:
- Direct Action: Tenant admin creates or terminates appointments directly in ProducerFlow
-
Immediate Status: Appointments are immediately set to
appointedorterminatedstatus - Webhook Notification: ProducerFlow sends a webhook notification immediately
- No Processing Delay: No waiting for external system processing
Triggered when a new appointment is created in the system.
NIPR Integration:
- After calling
RequestAppointmentRPC and NIPR accepts the request - The appointment is created with
in_progressstatus
ProducerFlow Direct:
- When tenant admin creates an appointment directly
- The appointment is immediately set to
appointedstatus
Triggered when an appointment's processing status changes.
NIPR Integration:
- NIPR completes processing of an appointment request (moves from
in_progresstoappointedorrejected) - NIPR completes processing of a termination request (moves from
termination_requestedtoterminated) - After calling
TerminateAppointmentRPC and NIPR processes the termination. The appointment status changes toterminated
ProducerFlow Direct:
- Tenant admin manually updates appointment status
- Status changes between
appointedandterminated
Understanding appointment processing statuses is crucial for handling webhook events. Different statuses are available depending on the integration type:
| Status | Description | Webhook Trigger |
|---|---|---|
in_progress |
Appointment request submitted to NIPR, awaiting processing | ✅ appointment.created
|
appointed |
NIPR successfully processed appointment request | ✅ appointment.updated
|
termination_requested |
Termination request submitted to NIPR, awaiting processing | ✅ appointment.updated
|
terminated |
NIPR successfully processed termination request | ✅ appointment.updated
|
rejected |
NIPR rejected the appointment request | ✅ appointment.updated
|
| Status | Description | Webhook Trigger |
|---|---|---|
appointed |
Appointment created/activated by tenant admin | ✅ appointment.created or appointment.updated
|
terminated |
Appointment terminated by tenant admin | ✅ appointment.updated
|
All appointment webhooks follow this structure:
{
"id": "string", // Unique event identifier
"event_type": "string", // appointment.created|updated|terminated
"origin": "string", // "ProducerFlowAPI", "ProducerFlowPortal"
"timestamp": "string", // ISO 8601 datetime
"appointment_id": "string", // Appointment identifier
"producer_id": "string", // Producer identifier (optional)
"agency_id": "string", // Agency identifier
"external_agency_id": "string", // External agency identifier
"external_producer_id": "string", // External producer identifier
"agency_npn": "string", // Agency National Producer Number
"producer_npn": "string", // Producer National Producer Number
"appointment_data": {
"carrier": "string", // Insurance carrier name
"state": "string", // State code (e.g., "TX")
"status": "string", // Processing status
"license_number": "string", // Associated license number
"effective_date": "string", // ISO 8601 datetime
"termination_date": "string", // ISO 8601 datetime (if terminated)
"reasons": ["string"], // Rejection or termination reasons
"appointment_type": "string", // registry|up_front|just_in_time
"fees_in_cents": "number", // Processing fees charged
"comments": "string" // Additional notes from NIPR
}
}When NIPR successfully processes an appointment request:
{
"id": "evt_appointment_abc123",
"event_type": "appointment.updated",
"origin": "NIPR",
"timestamp": "2025-01-15T14:30:00Z",
"appointment_id": "app_xyz789",
"producer_id": "prod_456789",
"agency_id": "agcy_123456",
"external_agency_id": "ext_agcy_001",
"external_producer_id": "ext_prod_002",
"agency_npn": "87654321",
"producer_npn": "12345678",
"appointment_data": {
"carrier": "State Farm Mutual Automobile Insurance Company",
"state": "TX",
"status": "appointed",
"license_number": "TX12345678",
"effective_date": "2025-01-15T14:30:00Z",
"appointment_type": "up_front",
"fees_in_cents": 5000,
}
}When NIPR rejects an appointment request:
{
"id": "evt_appointment_def456",
"event_type": "appointment.updated",
"origin": "ProducerFlowAPI",
"timestamp": "2025-01-15T14:45:00Z",
"appointment_id": "app_xyz790",
"producer_id": "prod_456790",
"agency_id": "agcy_123457",
"external_agency_id": "ext_agcy_002",
"external_producer_id": "ext_prod_003",
"agency_npn": "87654322",
"producer_npn": "12345679",
"appointment_data": {
"carrier": "Progressive Insurance Company",
"state": "CA",
"status": "rejected",
"license_number": "CA98765432",
"appointment_type": "registry",
"fees_in_cents": 0,
}
}When a termination request is submitted to NIPR but not yet processed:
{
"id": "evt_appointment_term_req_123",
"event_type": "appointment.updated",
"origin": "ProducerFlowAPI",
"timestamp": "2025-01-15T14:50:00Z",
"appointment_id": "app_xyz792",
"producer_id": "prod_456792",
"agency_id": "agcy_123459",
"external_agency_id": "ext_agcy_006",
"external_producer_id": "ext_prod_007",
"agency_npn": "87654326",
"producer_npn": "12345683",
"appointment_data": {
"carrier": "Allstate Insurance Company",
"state": "FL",
"status": "termination_requested",
"license_number": "FL55555555",
"effective_date": "2024-06-01T00:00:00Z",
"appointment_type": "registry",
"fees_in_cents": 2500,
}
}When NIPR successfully processes an appointment termination:
{
"id": "evt_appointment_ghi789",
"event_type": "appointment.updated",
"origin": "ProducerFlowAPI",
"timestamp": "2025-01-15T15:00:00Z",
"appointment_id": "app_xyz791",
"producer_id": "prod_456791",
"agency_id": "agcy_123458",
"external_agency_id": "ext_agcy_003",
"external_producer_id": "ext_prod_004",
"agency_npn": "87654323",
"producer_npn": "12345680",
"appointment_data": {
"carrier": "Allstate Insurance Company",
"state": "FL",
"status": "terminated",
"license_number": "FL55555555",
"effective_date": "2024-06-01T00:00:00Z",
"termination_date": "2025-01-15T15:00:00Z",
"appointment_type": "registry",
"fees_in_cents": 2500,
}
}When a tenant admin creates an appointment directly in ProducerFlow:
{
"id": "evt_appointment_direct_123",
"event_type": "appointment.created",
"origin": "ProducerFlowPortal",
"timestamp": "2025-01-15T16:15:00Z",
"appointment_id": "app_direct_456",
"producer_id": "prod_789123",
"agency_id": "agcy_456789",
"external_agency_id": "ext_agcy_004",
"external_producer_id": "ext_prod_005",
"agency_npn": "87654324",
"producer_npn": "12345681",
"appointment_data": {
"carrier": "Farmers Insurance Group",
"state": "NV",
"status": "appointed",
"license_number": "NV98765432",
"effective_date": "2025-01-15T16:15:00Z",
"appointment_type": "registry",
"fees_in_cents": 0,
}
}When a tenant admin terminates an appointment directly in ProducerFlow:
{
"id": "evt_appointment_direct_456",
"event_type": "appointment.updated",
"origin": "ProducerFlowPortal",
"timestamp": "2025-01-15T16:30:00Z",
"appointment_id": "app_direct_789",
"producer_id": "prod_789124",
"agency_id": "agcy_456790",
"external_agency_id": "ext_agcy_005",
"external_producer_id": "ext_prod_006",
"agency_npn": "87654325",
"producer_npn": "12345682",
"appointment_data": {
"carrier": "Liberty Mutual Insurance",
"state": "AZ",
"status": "terminated",
"license_number": "AZ11111111",
"effective_date": "2024-08-01T00:00:00Z",
"termination_date": "2025-01-15T16:30:00Z",
"appointment_type": "up_front",
"fees_in_cents": 0,
}
}-
Status-Based Handling: Handle webhook events based on appointment status:
-
in_progress= Only appears in NIPR integration, indicates appointment request processing -
appointed= Final status in both integration types -
termination_requested= Only appears in NIPR integration, indicates termination request processing -
terminated= Final status in both integration types -
rejected= Only appears in NIPR integration
-
-
Idempotency: Always use the
idfield to handle duplicate webhook deliveries -
Error Handling: Implement retry logic for failed webhook processing
-
Validation: Validate payloads against the appointment schema
| Aspect | NIPR Integration | ProducerFlow Direct |
|---|---|---|
| Processing | Asynchronous (minutes to hours) | Immediate |
| Initial Status | in_progress |
appointed |
| Origin Values |
ProducerFlowPortal, ProducerFlowAPI
|
ProducerFlowPortal, ProducerFlowAPI
|
| Possible Rejections | Yes (rejected) |
No |
| Fees | May include NIPR processing fees | $0 |
| Webhook Timing | Delayed until NIPR processes | Immediate |
Appointment and termination fees are included in webhook payloads as fees_in_cents:
- NIPR Integration: Values represent actual NIPR processing fees (e.g., 5000 = $50.00)
- ProducerFlow Direct: Typically 0 since no external processing fees apply
- Zero fees indicate no charge was applied
Handle these common error scenarios:
-
Rejection Reasons: Check
appointment_data.reasonsarray- Common reasons: expired license, missing CE credits, carrier restrictions
- Use reasons to guide remediation steps
-
Processing Delays:
- NIPR processing can take hours or days for both appointments and terminations
- Don't treat delayed webhooks as failures
- Monitor appointment status via API if needed
-
Termination Processing:
- Status moves from
appointed→termination_requested→terminated - Handle
termination_requestedstatus to notify users that termination is pending
- Status moves from
- Immediate Processing: No delays or external processing errors
- Admin Actions: All changes are intentional admin actions
- No Rejections: Direct appointments don't get rejected by external systems
-
RequestAppointment- Initiates appointment requests (NIPR integration) -
TerminateAppointment- Initiates termination requests (NIPR integration) -
GetAppointment- Retrieves current appointment status (both integrations) -
ListAppointments- Lists appointments with status filters (both integrations) -
GetAppointmentFees- Gets fee estimates before requesting (NIPR integration) -
GetTerminationFees- Gets termination fee estimates (NIPR integration) -
ListTerminationReasons- Gets valid termination reasons by state (NIPR integration)
- Verify webhook signatures using your webhook secret
- Use HTTPS endpoints for webhook URLs
- Implement proper authentication for webhook endpoints
- Log all webhook events for audit and debugging
For additional webhook documentation, see the main Webhooks guide.