careCycle
Webhooks

Events & Payloads

The careCycle webhook event catalog and example payloads for each event.

These are the events careCycle can deliver. When you add an endpoint you can subscribe to all events or only the ones you care about.

EventFires when
customer.createdA customer is created (manual entry, inbound call, lead capture, or an integration). Bulk CSV imports do not emit this event.
customer.updatedA customer's details are edited.
customer.unsubscribedA customer opts out of contact: they reply STOP to a text, a carrier block is applied, or a rep marks them do-not-call / do-not-SMS.
call.completedA call finishes and its details (transcript, duration, disposition) are finalized.
sms.sentAn outbound SMS/RCS message is sent to a customer (campaign, appointment, or a manual reply from the inbox).
sms.receivedAn inbound SMS/RCS message is received from a customer.
inbox.conversation_marked_doneA rep marks an inbox conversation (thread) as done.
inquiry.callback_scheduledA rep resolves a customer inquiry by scheduling an AI callback.
policy.createdA policy is added to a customer (manual entry, call form, or an integration). Bulk CSV imports do not emit this event.
policy.updatedA policy's details are edited (including status changes).
appointment.scheduledAn appointment is booked for a customer (by the voice AI, a rep in the dashboard, or the customer via a self-serve scheduling link).
appointment.confirmedA customer confirms their appointment.
appointment.rescheduledAn appointment is moved to a new time.
appointment.cancelledAn appointment is cancelled.
appointment.no_showA customer does not show up for their appointment.
appointment.completedAn appointment takes place and is marked complete.
appointment.member_reassignedAn appointment is reassigned to a different team member.

Every payload includes a top-level event_type field (e.g. "customer.created"); switch on it to route events. This matters most for customer.created and customer.updated, which are otherwise identical in shape. The same value is also sent as the Svix event type for endpoint-level subscription filtering.

All IDs are UUIDs, timestamps are ISO 8601, and any field with no value is null. Phone numbers are E.164.

customer.created

Sent when a new customer record is created. The payload is the full customer object.

{
  "event_type": "customer.created",
  "id": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
  "createdAt": "2026-06-17T19:07:23.709Z",
  "updatedAt": "2026-06-17T19:07:23.709Z",
  "externalId": "CRM-48213",
  "status": "Lead",
  "firstName": "Marcus",
  "middleName": null,
  "lastName": "Delacroix",
  "salutation": null,
  "suffix": null,
  "preferredName": null,
  "phoneNumber": "+13128471928",
  "lineType": "mobile",
  "email": "marcus.delacroix@example.com",
  "dateOfBirth": "1958-04-12",
  "language": "en",
  "ethnicity": null,
  "gender": "Male",
  "maritalStatus": "Married",
  "address": "4427 Westbrook Ave",
  "address2": "Apt 3B",
  "city": "Mesa",
  "county": "Maricopa",
  "state": "AZ",
  "postalCode": "85204",
  "timezone": "America/Phoenix",
  "mbiNumber": "1EG4TE5MK73",
  "medicareCard": true,
  "medicarePartADate": "2023-05-01",
  "medicarePartBDate": "2023-05-01",
  "hasMedicaid": false,
  "medicaidNumber": null,
  "socialSecurityDisability": false,
  "veteran": true,
  "vaNumber": null,
  "householdIncome": 42000,
  "annualIncome": 42000,
  "filingStatus": "married_joint",
  "dependentCount": 0,
  "subsidyEligible": true,
  "subsidyAmount": 148,
  "carrierAssignedCustomerId": null,
  "agentName": null,
  "agentNpn": null,
  "assignedUser": {
    "id": "b396018f-7d49-4a55-abe5-544174abcaaa",
    "name": "Priya Raman",
    "email": "priya@youragency.com",
    "npn": "8419302",
    "role": "agent",
    "licensedStates": ["AZ", "AR"]
  },
  "doNotCall": false,
  "doNotSMS": false,
  "doNotEmail": false,
  "doNotMail": false,
  "testCustomer": false
}

Every field below is present on customer.created and customer.updated. Any field without a value is null.

Identifiers & status

FieldTypeDescription
event_typestringThe webhook event: customer.created or customer.updated. Switch on this to route the event
idUUIDcareCycle customer ID
createdAt / updatedAtISO 8601When the record was created / last updated
externalIdstringYour own identifier for the customer, if one was provided
statusenumLifecycle status: one of Lead, Active, Inactive
carrierAssignedCustomerIdstringThe carrier's identifier for the customer, if known
testCustomerbooleantrue for test records; filter these out in production

Identity & contact

FieldTypeDescription
firstName / middleName / lastNamestringLegal name parts
salutation / suffix / preferredNamestringOptional name extras
phoneNumberstringPrimary phone number (E.164)
lineTypeenumCarrier line type: landline, mobile, fixedVoip, nonFixedVoip, personal, tollFree, premium, sharedCost, uan, voicemail, pager, or unknown
emailstringEmail address
dateOfBirthdateYYYY-MM-DD (a date, not a timestamp)
languagestringISO 639-1 language code (e.g. en, es)
ethnicitystringFree-text ethnicity, if collected
genderenumMale, Female, Non-Binary, Other, or Prefer Not to Say
maritalStatusenumSingle, Married, Divorced, Widowed, Separated, or Domestic Partnership

Address

FieldTypeDescription
address / address2stringStreet address lines
city / county / state / postalCodestringLocality fields; state is the 2-letter US abbreviation
timezonestringIANA timezone (e.g. America/Phoenix)

Medicare & Medicaid

FieldTypeDescription
mbiNumberstringMedicare Beneficiary Identifier
medicareCardbooleanWhether the customer has their Medicare card
medicarePartADate / medicarePartBDatedateYYYY-MM-DD Part A / Part B effective dates
hasMedicaidbooleanWhether the customer has Medicaid
medicaidNumberstringMedicaid ID, if applicable
socialSecurityDisabilitybooleanReceiving SSDI
veteranbooleanVeteran status
vaNumberstringVA identifier, if applicable

Financial & subsidy

FieldTypeDescription
householdIncome / annualIncomeintegerWhole US dollars (no cents)
filingStatusstringTax filing status (e.g. single, married_joint, head_of_household)
dependentCountintegerNumber of dependents
subsidyEligiblebooleanEligible for a premium subsidy
subsidyAmountintegerEstimated monthly subsidy in whole US dollars

Assignment

FieldTypeDescription
agentName / agentNpnstringExternally-supplied agent name and NPN, if provided
assignedUserobjectThe careCycle member assigned to the customer, or null if unassigned. Contains id, name, email, npn, role, and licensedStates (array of 2-letter US state codes)

Consent flags

FieldTypeDescription
doNotCall / doNotSMS / doNotEmail / doNotMailbooleanPer-channel contact suppression; respect these before reaching out

customer.updated

Sent when a customer is edited. The payload is identical in shape to customer.created and reflects the customer's state after the update. updatedAt changes on every update.

{
  "event_type": "customer.updated",
  "id": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
  "updatedAt": "2026-06-18T14:22:09.120Z",
  "status": "Active",
  "phoneNumber": "+13128471928",
  "firstName": "Marcus",
  "lastName": "Delacroix",
  "...": "all other customer fields, same shape as customer.created"
}

customer.unsubscribed

Sent when a customer is newly opted out of contact on one or more channels. This fires on the transition into a suppressed state, whether the customer replies STOP to a text, the carrier applies a block, or a rep marks them do-not-call / do-not-SMS in the dashboard. Because a do-not-SMS opt-out also suppresses calls, a single STOP typically reports both call and sms in channels.

channels lists only the channels that flipped to suppressed on this event. source is one of inbound_message, carrier_block, or manual. The embedded customer (same object as customer.created) reflects the resulting doNotCall / doNotSMS / doNotEmail / doNotMail flags.

{
  "event_type": "customer.unsubscribed",
  "customerId": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
  "unsubscribedAt": "2026-07-13T18:04:51.220Z",
  "source": "inbound_message",
  "channels": ["call", "sms"],
  "customer": {
    "id": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
    "doNotCall": true,
    "doNotSMS": true,
    "...": "full customer object, same shape as customer.created"
  }
}

call.completed

Sent once a call has finished and its details are finalized. The payload includes the call outcome, the full transcript and summary, the campaign it belonged to, and the associated customer (the same object as customer.created).

{
  "event_type": "call.completed",
  "id": "dca4a483-af54-4899-a804-766ee5812537",
  "createdAt": "2026-06-17T19:07:23.709Z",
  "phoneNumber": "+13128471928",
  "callSid": "f2a91c0b-7d2e-4c8a-9f31-6b5d0a4e1c77",
  "direction": "inbound",
  "disposition": "Enrolled",
  "durationMs": 247000,
  "startTime": "2026-06-17T19:03:16.001Z",
  "endTime": "2026-06-17T19:07:23.001Z",
  "endedReason": "completed",
  "summary": "Caller confirmed eligibility and enrolled in a Medicare Advantage plan effective July 1.",
  "transcript": "Agent: Thanks for calling careCycle...\nCaller: Hi, I'd like to review my options...",
  "campaign": {
    "id": "4f952597-5c04-4d2c-851e-30f518e2c761",
    "name": "MA Inbound Receptionist",
    "slug": null,
    "description": null,
    "status": "active",
    "vertical": "medicare",
    "suite": "receptionist",
    "direction": "inbound",
    "kind": "voice_ai",
    "tags": [],
    "startDate": "2026-03-06T00:11:35.256Z",
    "endDate": null
  },
  "customer": {
    "id": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
    "...": "full customer object, same shape as customer.created"
  }
}
FieldDescription
event_typeThe webhook event: always call.completed
idcareCycle call ID
phoneNumberThe customer's phone number (E.164)
directioninbound or outbound
dispositionFinal outcome of the call
durationMsCall duration in milliseconds
endedReasonWhy the call ended (e.g. completed, no-answer)
summaryAI-generated summary of the call
transcriptFull call transcript
campaignThe campaign the call belonged to (null if none)
customerThe associated customer (null if the call wasn't linked to one)

call.completed fires for every terminal call, including no-answer, busy, and failed. Use disposition and endedReason to distinguish outcomes.

sms.sent

Sent when an outbound SMS or RCS message is delivered to a customer, whether from a campaign, an appointment workflow, or a manual reply in the inbox. The payload carries the message fields plus the associated customer (the same object as customer.created).

{
  "event_type": "sms.sent",
  "id": "9b1c2d3e-4f50-4a61-8b72-0c3d4e5f6a7b",
  "createdAt": "2026-06-25T16:48:02.114Z",
  "direction": "outbound",
  "fromNumber": "+18005551234",
  "toNumber": "+13128471928",
  "content": "Hi Marcus, just confirming your appointment tomorrow at 2pm.",
  "smsType": "appointment_reminder",
  "channel": "telnyx_sms",
  "campaignId": "4f952597-5c04-4d2c-851e-30f518e2c761",
  "sentAt": "2026-06-25T16:48:02.000Z",
  "sentBy": null,
  "customer": {
    "id": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
    "...": "full customer object, same shape as customer.created"
  }
}

sentBy is null for automated sends (campaigns, appointment workflows, bots). When a rep sends a message manually from the inbox, it identifies that team member:

{
  "sentBy": {
    "id": "7c9e1a2b-3d4e-4f50-8a61-9b0c1d2e3f40",
    "name": "Jordan Smith",
    "email": "jordan@youragency.com",
    "npn": "1234567",
    "role": "agent",
    "licensedStates": ["IL", "IN"]
  }
}

sms.received

Sent when an inbound SMS or RCS message is received from a customer. Identical in shape to sms.sent with direction set to inbound. customer is null when the inbound number can't be matched to a known customer.

{
  "event_type": "sms.received",
  "id": "a2b3c4d5-6e70-4f81-9a02-1b3c4d5e6f70",
  "createdAt": "2026-06-25T16:50:31.882Z",
  "direction": "inbound",
  "fromNumber": "+13128471928",
  "toNumber": "+18005551234",
  "content": "Yes, that works. See you then!",
  "smsType": "inbound_sms",
  "channel": "telnyx_sms",
  "campaignId": null,
  "sentAt": "2026-06-25T16:50:31.000Z",
  "sentBy": null,
  "customer": {
    "id": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
    "...": "full customer object, same shape as customer.created"
  }
}
FieldTypeDescription
event_typestringsms.sent or sms.received
idUUIDcareCycle SMS record ID
createdAtISO 8601When the record was created
directionenumoutbound (sms.sent) or inbound (sms.received)
fromNumber / toNumberstringSender / recipient phone numbers (E.164)
contentstringMessage body
smsTypestringInternal classification (e.g. appointment_reminder, inbox_reply, inbound_sms, inbound_mms, inbound_rcs)
channelenumMessaging channel (e.g. tells, telnyx_sms, telnyx_rcs)
campaignIdUUIDThe campaign the message belonged to, or null
sentAtISO 8601When the message was sent / received
sentByobjectThe team member who sent the message (id, name, email, npn, role, licensedStates). null for automated/campaign/system sends and all inbound messages.
customerobjectThe associated customer (null if not linked)

inbox.conversation_marked_done

Sent when a rep marks an inbox conversation (thread) as done. Carries the thread and customer ids, who marked it done, and the associated customer.

{
  "event_type": "inbox.conversation_marked_done",
  "threadId": "c3d4e5f6-7a80-4b91-8c12-2d4e5f6a7b81",
  "customerId": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
  "markedDoneAt": "2026-06-25T16:52:10.044Z",
  "markedBy": {
    "memberId": "d4e5f6a7-8b90-4c01-9d22-3e4f5a6b7c82",
    "userId": "b396018f-7d49-4a55-abe5-544174abcaaa",
    "name": "Priya Raman",
    "email": "priya@youragency.com"
  },
  "customer": {
    "id": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
    "...": "full customer object, same shape as customer.created"
  }
}
FieldTypeDescription
event_typestringAlways inbox.conversation_marked_done
threadIdUUIDThe inbox thread that was closed
customerIdUUIDThe customer the thread belongs to
markedDoneAtISO 8601When the thread was marked done
markedByobjectThe member who closed it: memberId, userId, name, email (null if unavailable)
customerobjectThe associated customer (null if not found)

inquiry.callback_scheduled

Sent when a rep resolves a customer inquiry by scheduling an AI callback: the voice AI will call the customer back to follow up. Carries the inquiry context, who scheduled it, the estimated callback time, and the associated customer (the same object as customer.created).

{
  "event_type": "inquiry.callback_scheduled",
  "inquiryId": "e5f6a7b8-9c01-4d22-8e33-4f5a6b7c8d90",
  "customerCampaignId": "4f952597-5c04-4d2c-851e-30f518e2c761",
  "inquiry": "Wants to confirm whether her current cardiologist is in-network before switching plans.",
  "primaryCategory": "plan_benefits",
  "severity": "medium",
  "callbackScheduledFor": "2026-06-30T13:00:00.000Z",
  "callbackRequestedAt": "2026-06-29T21:14:38.512Z",
  "scheduledBy": {
    "id": "7c9e1a2b-3d4e-4f50-8a61-9b0c1d2e3f40",
    "name": "Jordan Smith",
    "email": "jordan@youragency.com",
    "npn": "1234567",
    "role": "agent",
    "licensedStates": ["IL", "IN"]
  },
  "customer": {
    "id": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
    "...": "full customer object, same shape as customer.created"
  }
}
FieldTypeDescription
event_typestringAlways inquiry.callback_scheduled
inquiryIdUUIDThe inquiry the callback resolves
customerCampaignIdUUIDThe customer-campaign the inquiry belongs to
inquirystringThe customer's question or request
primaryCategorystringInquiry category, if classified (null otherwise)
severitystringInquiry severity, if classified (null otherwise)
callbackScheduledForISO 8601 | nullEstimated first-attempt time, respecting the customer's calling window. An estimate at scheduling time; the actual call may be placed later as it's rescheduled around compliance windows. null when no compliant window estimate is available at scheduling time
callbackRequestedAtISO 8601When the rep scheduled the callback
scheduledByobjectThe member who scheduled it (id, name, email, npn, role, licensedStates), or null
customerobjectThe associated customer (null if not found)

policy.created

Sent when a policy is added to a customer. The payload is the full policy object plus the associated customer (the same object as customer.created). Monetary fields are decimal strings, dates are YYYY-MM-DD, and any field with no value is null.

{
  "event_type": "policy.created",
  "id": "7a2f9c14-8b3d-4e6f-9a01-2c3d4e5f6a7b",
  "createdAt": "2026-06-17T19:10:44.512Z",
  "updatedAt": "2026-06-17T19:10:44.512Z",
  "customerId": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
  "policyType": "MAPD",
  "policySubType": "HMO",
  "policyNumber": "MAPD-5582013",
  "applicationId": "APP-99213",
  "carrierId": "c9d0e1f2-3a4b-4c5d-8e6f-7a8b9c0d1e2f",
  "carrierName": "Aetna",
  "planName": "Aetna Medicare Elite (HMO)",
  "planCode": "H1290-036-001",
  "carrierAssignedPolicyId": null,
  "healthSherpaPolicyId": null,
  "sunFireEnrollmentCode": null,
  "hiosId": null,
  "metalLevel": null,
  "status": "Active",
  "applicationApprovalDate": "2026-06-17",
  "effectiveDate": "2026-07-01",
  "terminationDate": null,
  "renewalDate": null,
  "enrollmentDate": "2026-06-17",
  "cancelledDate": null,
  "declineReason": null,
  "declineReasonDescription": null,
  "cancellationReason": null,
  "cancellationReasonDescription": null,
  "electionPeriod": "AEP",
  "gracePeriodStartDate": null,
  "paidThroughDate": null,
  "ffmApplicationId": null,
  "ffmSubscriberId": null,
  "aorFirstName": "Priya",
  "aorLastName": "Raman",
  "aorNpn": "8419302",
  "writingAgentNpn": "8419302",
  "writingAgentName": "Priya Raman",
  "sepType": null,
  "sepCode": null,
  "sepStartDate": null,
  "sepEndDate": null,
  "sepDocumentationReceived": false,
  "sepDocumentationDate": null,
  "sepNotes": null,
  "monthlyPremium": "0.00",
  "deductible": "590.00",
  "outOfPocketMax": "8300.00",
  "subsidyAmount": null,
  "usingSubsidy": false,
  "premiumMode": "Monthly",
  "paymentMode": "ACH",
  "paymentMethod": "ACH / Bank Draft",
  "grossPremium": null,
  "netPremium": null,
  "initialCommission": "611.00",
  "renewalCommission": "305.00",
  "spifAmount": null,
  "policyLives": 1,
  "wasAgent": true,
  "writtenAs": "New Business",
  "isReplacing": null,
  "isRewrite": false,
  "hospitalNetwork": null,
  "pcpNetwork": null,
  "ssbciVerificationRequired": false,
  "dailyBenefit": null,
  "eliminationPeriod": null,
  "benefitPeriod": null,
  "hasCola": false,
  "deathBenefit": null,
  "term": null,
  "maturityDate": null,
  "riders": null,
  "exchangeStatus": null,
  "billingMethod": null,
  "benefitReminder": null,
  "surveyCompleted": false,
  "reasonForPurchase": null,
  "policyNotes": null,
  "customer": {
    "id": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
    "...": "full customer object, same shape as customer.created"
  }
}

Every field below is present on policy.created and policy.updated. Any field without a value is null.

Identifiers & plan

FieldTypeDescription
event_typestringThe webhook event: policy.created or policy.updated. Switch on this to route the event
idUUIDcareCycle policy ID
createdAt / updatedAtISO 8601When the policy was created / last updated
customerIdUUIDThe customer the policy belongs to
policyTypeenumProduct type, e.g. MA, MAPD, PDP, MS, ACA, Life, Annuity, LTC
policySubTypestringSub-type within the product family (e.g. HMO, PPO, Plan G)
policyNumber / applicationIdstringCarrier policy number / application identifier
carrierIdUUIDcareCycle carrier ID (null if unresolved)
carrierNamestringInsurance carrier name
planName / planCodestringPlan name and code (e.g. H1290-036-001)
carrierAssignedPolicyId / healthSherpaPolicyId / sunFireEnrollmentCodestringExternal identifiers from carrier and enrollment systems
hiosId / metalLevelstringACA plan ID and metal tier (Bronze, Silver, Gold, Platinum, Catastrophic, Expanded Bronze)

Status & dates

FieldTypeDescription
statusenumPolicy status, e.g. Active, Placed, Pending, Suspended, Cancelled, Terminated, Future Cancel, Not Approved
applicationApprovalDate / effectiveDate / terminationDate / renewalDate / enrollmentDate / cancelledDatedateKey policy dates (YYYY-MM-DD)
declineReason / declineReasonDescriptionstringWhy an application was declined (Not Approved)
cancellationReason / cancellationReasonDescriptionstringWhy a policy was cancelled
electionPeriodenumEnrollment period: IEP, AEP, OEP, SEP, ICEP, MA-OEP

Enrollment & marketplace (ACA)

FieldTypeDescription
gracePeriodStartDate / paidThroughDatedateACA effectuation dates
ffmApplicationId / ffmSubscriberIdstringFederal marketplace identifiers
exchangeStatusenumFFM, SBM, SBM FP, OFF EXCHANGE, PRIVATE EXCHANGE, UNKNOWN
sepType / sepCodestringSpecial Enrollment Period type and code
sepStartDate / sepEndDate / sepDocumentationDatedateSEP window and documentation dates
sepDocumentationReceivedbooleanWhether SEP documentation has been received
sepNotesstringFree-text SEP notes

Agent of record

FieldTypeDescription
aorFirstName / aorLastName / aorNpnstringAgent of record name and NPN
writingAgentName / writingAgentNpnstringWriting agent name and NPN

Financial

FieldTypeDescription
monthlyPremium / grossPremium / netPremiumdecimal stringPremium amounts (gross is before subsidy, net after)
deductible / outOfPocketMaxdecimal stringCost-sharing amounts
subsidyAmount / usingSubsidydecimal string / booleanSubsidy amount and whether it's applied
premiumModeenumMonthly, Quarterly, Semi-Annual, Annual
paymentModeenumACH, Credit/ debit card, Direct bill
paymentMethodenumCredit Card, Debit Card, Check, ACH / Bank Draft, Money Order, Cash, Other
initialCommission / renewalCommission / spifAmountdecimal stringCommission and incentive amounts

Coverage details

FieldTypeDescription
policyLivesintegerNumber of people covered
wasAgentbooleanWhether an agent was involved in the enrollment
writtenAsenumNew Business, Like Plan Change, Unlike Plan Change, Reinstatement, Rewrite
isReplacing / isRewritestring / booleanWhat the policy replaces, and whether it's a rewrite
hospitalNetwork / pcpNetworkstringMedicare network details
ssbciVerificationRequiredbooleanWhether SSBCI (Special Supplemental Benefits for the Chronically Ill) verification is required, for MA/MAPD plans
dailyBenefit / eliminationPeriod / benefitPeriod / hasColadecimal string / integer / integer / booleanLong-term care benefit details
deathBenefit / term / maturityDate / ridersdecimal string / integer / date / stringLife insurance details
billingMethod / benefitReminder / surveyCompletedstring / date / booleanCompliance and billing tracking
reasonForPurchase / policyNotesstringFree-text notes
customerobjectThe associated customer (same shape as customer.created; null if not found)

policy.updated

Sent when a policy is edited, including status changes such as a policy moving to Active, Cancelled, or Not Approved. The payload is identical in shape to policy.created and reflects the policy's state after the update. updatedAt changes on every update.

{
  "event_type": "policy.updated",
  "id": "7a2f9c14-8b3d-4e6f-9a01-2c3d4e5f6a7b",
  "updatedAt": "2026-06-18T15:02:41.880Z",
  "customerId": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
  "status": "Cancelled",
  "cancellationReason": "Moved out of service area",
  "cancelledDate": "2026-06-18",
  "...": "all other policy fields, same shape as policy.created"
}

appointment.scheduled

Sent when an appointment is booked for a customer, whether by the voice AI during a call, a rep in the dashboard, or the customer via a self-serve scheduling link. Every appointment.* event carries the same base appointment object plus the nested customer (the same object as customer.created), member, campaign, and appointmentConfig, the actor that performed the action, and (for some events) a few extra fields describing the change.

{
  "event_type": "appointment.scheduled",
  "id": "8d1a2b3c-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  "createdAt": "2026-06-17T19:07:23.709Z",
  "updatedAt": "2026-06-17T19:07:23.709Z",
  "startTime": "2026-06-20T18:00:00.000Z",
  "endTime": "2026-06-20T18:30:00.000Z",
  "timezone": "America/Phoenix",
  "status": "scheduled",
  "bookingSource": "ai_assistant",
  "appointmentMode": "phone_call",
  "title": "30 Min Medicare Review between Priya Raman and Marcus Delacroix",
  "location": null,
  "meetingUrl": null,
  "confirmedAt": null,
  "cancelledAt": null,
  "cancellationReason": null,
  "originCallId": "dca4a483-af54-4899-a804-766ee5812537",
  "actor": {
    "kind": "ai_assistant",
    "callId": "dca4a483-af54-4899-a804-766ee5812537",
    "toolCallId": "call_9fB2xk"
  },
  "member": {
    "id": "d4e5f6a7-8b90-4c01-9d22-3e4f5a6b7c82",
    "name": "Priya Raman",
    "email": "priya@youragency.com",
    "npn": "8419302",
    "role": "agent",
    "licensedStates": ["AZ", "AR"]
  },
  "campaign": {
    "id": "4f952597-5c04-4d2c-851e-30f518e2c761",
    "name": "MA Inbound Receptionist",
    "slug": null,
    "description": null,
    "status": "active",
    "vertical": "medicare",
    "suite": "receptionist",
    "direction": "inbound",
    "kind": "voice_ai",
    "tags": [],
    "startDate": "2026-03-06T00:11:35.256Z",
    "endDate": null
  },
  "appointmentConfig": {
    "id": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
    "name": "Medicare Review",
    "appointmentLength": 30,
    "appointmentMode": "phone_call"
  },
  "customer": {
    "id": "b1f7c0e2-3a4d-4e5f-8a9b-0c1d2e3f4a5b",
    "...": "full customer object, same shape as customer.created"
  }
}

Every field below is present on all appointment.* events. Any field without a value is null.

Appointment

FieldTypeDescription
event_typestringThe webhook event, e.g. appointment.scheduled. Switch on this to route the event
idUUIDcareCycle appointment ID (stable across the appointment's lifecycle)
createdAt / updatedAtISO 8601When the appointment was created / last updated
startTime / endTimeISO 8601The scheduled window (UTC; use timezone to localize)
timezonestringIANA timezone the appointment was booked in (e.g. America/Chicago)
statusenumscheduled, confirmed, cancelled, completed, or no_show
bookingSourceenumHow it was booked: ai_assistant, manual, or scheduling_page
appointmentModeenumHow the appointment takes place. phone_call (the voice AI dials the customer) and agent_phone_call (an assigned rep dials from the softphone) are the fully supported modes today. video_call and in_person are defined but not fully supported yet
titlestringHuman-readable appointment title
locationstringPhysical address for in_person meetings. in_person is not fully supported yet, so this is null in practice
meetingUrlstringJoin URL for video_call meetings. video_call is not fully supported yet, so this is null in practice
confirmedAtISO 8601When the appointment was confirmed (null until confirmed)
cancelledAtISO 8601When the appointment was cancelled (null unless cancelled)
cancellationReasonstringWhy the appointment was cancelled (null unless cancelled)
originCallIdUUIDThe call the appointment was booked on. Matches the id on the call.completed event for the same call, so you can join the two. null for manual and scheduling-page bookings

Actor, participants & context

FieldTypeDescription
actorobjectWho performed the action. Always has a kind discriminator: user (a rep; userId, userName), customer (customerId), ai_assistant (callId, toolCallId), or system (reason)
memberobjectThe team member the appointment is assigned to (id, name, email, npn, role, licensedStates), or null if unassigned
campaignobjectThe campaign the appointment belongs to (same shape as on call.completed), or null
appointmentConfigobjectThe appointment type it was booked under: id, name, appointmentLength (minutes), appointmentMode. null for older appointments that predate configs
customerobjectThe associated customer (same shape as customer.created)

appointment.confirmed

Sent when a customer confirms their appointment. Identical in shape to appointment.scheduled, with status set to confirmed and confirmedAt populated.

appointment.rescheduled

Sent when an appointment is moved to a new time. Identical in shape to appointment.scheduled (the base fields reflect the new time), plus the previous and new windows:

{
  "event_type": "appointment.rescheduled",
  "id": "8d1a2b3c-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  "startTime": "2026-06-22T20:00:00.000Z",
  "endTime": "2026-06-22T20:30:00.000Z",
  "fromStartTime": "2026-06-20T18:00:00.000Z",
  "toStartTime": "2026-06-22T20:00:00.000Z",
  "fromEndTime": "2026-06-20T18:30:00.000Z",
  "toEndTime": "2026-06-22T20:30:00.000Z",
  "...": "all other appointment fields, same shape as appointment.scheduled"
}
FieldTypeDescription
fromStartTime / toStartTimeISO 8601The appointment's start time before and after the move
fromEndTime / toEndTimeISO 8601The appointment's end time before and after the move

appointment.cancelled

Sent when an appointment is cancelled. Identical in shape to appointment.scheduled, with status set to cancelled and cancelledAt populated, plus the cancellation reason:

{
  "event_type": "appointment.cancelled",
  "id": "8d1a2b3c-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  "status": "cancelled",
  "cancelledAt": "2026-06-19T15:02:41.880Z",
  "reason": "Customer requested to cancel",
  "...": "all other appointment fields, same shape as appointment.scheduled"
}
FieldTypeDescription
reasonstringWhy the appointment was cancelled (null if none was given). Also mirrored on the base cancellationReason field

appointment.no_show

Sent when a customer does not show up for their appointment. Identical in shape to appointment.scheduled, with status set to no_show.

appointment.completed

Sent when an appointment takes place and is marked complete (by the call outcome, a rep, or an automated resolution). Identical in shape to appointment.scheduled, with status set to completed.

appointment.member_reassigned

Sent when an appointment is reassigned to a different team member. Identical in shape to appointment.scheduled (the base member reflects the new assignee), plus the previous and new member ids:

{
  "event_type": "appointment.member_reassigned",
  "id": "8d1a2b3c-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
  "fromMemberId": "d4e5f6a7-8b90-4c01-9d22-3e4f5a6b7c82",
  "toMemberId": "f6a7b8c9-0d12-4e34-9f56-7a8b9c0d1e2f",
  "member": {
    "id": "f6a7b8c9-0d12-4e34-9f56-7a8b9c0d1e2f",
    "name": "Jordan Smith",
    "email": "jordan@youragency.com",
    "npn": "1234567",
    "role": "agent",
    "licensedStates": ["IL", "IN"]
  },
  "...": "all other appointment fields, same shape as appointment.scheduled"
}
FieldTypeDescription
fromMemberIdUUIDThe member the appointment was assigned to before (null if it was unassigned)
toMemberIdUUIDThe member it is now assigned to (null if it was unassigned)

On this page