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.
| Event | Fires when |
|---|---|
customer.created | A customer is created (manual entry, inbound call, lead capture, or an integration). Bulk CSV imports do not emit this event. |
customer.updated | A customer's details are edited. |
customer.unsubscribed | A 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.completed | A call finishes and its details (transcript, duration, disposition) are finalized. |
sms.sent | An outbound SMS/RCS message is sent to a customer (campaign, appointment, or a manual reply from the inbox). |
sms.received | An inbound SMS/RCS message is received from a customer. |
inbox.conversation_marked_done | A rep marks an inbox conversation (thread) as done. |
inquiry.callback_scheduled | A rep resolves a customer inquiry by scheduling an AI callback. |
policy.created | A policy is added to a customer (manual entry, call form, or an integration). Bulk CSV imports do not emit this event. |
policy.updated | A policy's details are edited (including status changes). |
appointment.scheduled | An 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.confirmed | A customer confirms their appointment. |
appointment.rescheduled | An appointment is moved to a new time. |
appointment.cancelled | An appointment is cancelled. |
appointment.no_show | A customer does not show up for their appointment. |
appointment.completed | An appointment takes place and is marked complete. |
appointment.member_reassigned | An 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
| Field | Type | Description |
|---|---|---|
event_type | string | The webhook event: customer.created or customer.updated. Switch on this to route the event |
id | UUID | careCycle customer ID |
createdAt / updatedAt | ISO 8601 | When the record was created / last updated |
externalId | string | Your own identifier for the customer, if one was provided |
status | enum | Lifecycle status: one of Lead, Active, Inactive |
carrierAssignedCustomerId | string | The carrier's identifier for the customer, if known |
testCustomer | boolean | true for test records; filter these out in production |
Identity & contact
| Field | Type | Description |
|---|---|---|
firstName / middleName / lastName | string | Legal name parts |
salutation / suffix / preferredName | string | Optional name extras |
phoneNumber | string | Primary phone number (E.164) |
lineType | enum | Carrier line type: landline, mobile, fixedVoip, nonFixedVoip, personal, tollFree, premium, sharedCost, uan, voicemail, pager, or unknown |
email | string | Email address |
dateOfBirth | date | YYYY-MM-DD (a date, not a timestamp) |
language | string | ISO 639-1 language code (e.g. en, es) |
ethnicity | string | Free-text ethnicity, if collected |
gender | enum | Male, Female, Non-Binary, Other, or Prefer Not to Say |
maritalStatus | enum | Single, Married, Divorced, Widowed, Separated, or Domestic Partnership |
Address
| Field | Type | Description |
|---|---|---|
address / address2 | string | Street address lines |
city / county / state / postalCode | string | Locality fields; state is the 2-letter US abbreviation |
timezone | string | IANA timezone (e.g. America/Phoenix) |
Medicare & Medicaid
| Field | Type | Description |
|---|---|---|
mbiNumber | string | Medicare Beneficiary Identifier |
medicareCard | boolean | Whether the customer has their Medicare card |
medicarePartADate / medicarePartBDate | date | YYYY-MM-DD Part A / Part B effective dates |
hasMedicaid | boolean | Whether the customer has Medicaid |
medicaidNumber | string | Medicaid ID, if applicable |
socialSecurityDisability | boolean | Receiving SSDI |
veteran | boolean | Veteran status |
vaNumber | string | VA identifier, if applicable |
Financial & subsidy
| Field | Type | Description |
|---|---|---|
householdIncome / annualIncome | integer | Whole US dollars (no cents) |
filingStatus | string | Tax filing status (e.g. single, married_joint, head_of_household) |
dependentCount | integer | Number of dependents |
subsidyEligible | boolean | Eligible for a premium subsidy |
subsidyAmount | integer | Estimated monthly subsidy in whole US dollars |
Assignment
| Field | Type | Description |
|---|---|---|
agentName / agentNpn | string | Externally-supplied agent name and NPN, if provided |
assignedUser | object | The 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
| Field | Type | Description |
|---|---|---|
doNotCall / doNotSMS / doNotEmail / doNotMail | boolean | Per-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"
}
}| Field | Description |
|---|---|
event_type | The webhook event: always call.completed |
id | careCycle call ID |
phoneNumber | The customer's phone number (E.164) |
direction | inbound or outbound |
disposition | Final outcome of the call |
durationMs | Call duration in milliseconds |
endedReason | Why the call ended (e.g. completed, no-answer) |
summary | AI-generated summary of the call |
transcript | Full call transcript |
campaign | The campaign the call belonged to (null if none) |
customer | The 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"
}
}| Field | Type | Description |
|---|---|---|
event_type | string | sms.sent or sms.received |
id | UUID | careCycle SMS record ID |
createdAt | ISO 8601 | When the record was created |
direction | enum | outbound (sms.sent) or inbound (sms.received) |
fromNumber / toNumber | string | Sender / recipient phone numbers (E.164) |
content | string | Message body |
smsType | string | Internal classification (e.g. appointment_reminder, inbox_reply, inbound_sms, inbound_mms, inbound_rcs) |
channel | enum | Messaging channel (e.g. tells, telnyx_sms, telnyx_rcs) |
campaignId | UUID | The campaign the message belonged to, or null |
sentAt | ISO 8601 | When the message was sent / received |
sentBy | object | The team member who sent the message (id, name, email, npn, role, licensedStates). null for automated/campaign/system sends and all inbound messages. |
customer | object | The 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"
}
}| Field | Type | Description |
|---|---|---|
event_type | string | Always inbox.conversation_marked_done |
threadId | UUID | The inbox thread that was closed |
customerId | UUID | The customer the thread belongs to |
markedDoneAt | ISO 8601 | When the thread was marked done |
markedBy | object | The member who closed it: memberId, userId, name, email (null if unavailable) |
customer | object | The 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"
}
}| Field | Type | Description |
|---|---|---|
event_type | string | Always inquiry.callback_scheduled |
inquiryId | UUID | The inquiry the callback resolves |
customerCampaignId | UUID | The customer-campaign the inquiry belongs to |
inquiry | string | The customer's question or request |
primaryCategory | string | Inquiry category, if classified (null otherwise) |
severity | string | Inquiry severity, if classified (null otherwise) |
callbackScheduledFor | ISO 8601 | null | Estimated 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 |
callbackRequestedAt | ISO 8601 | When the rep scheduled the callback |
scheduledBy | object | The member who scheduled it (id, name, email, npn, role, licensedStates), or null |
customer | object | The 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
| Field | Type | Description |
|---|---|---|
event_type | string | The webhook event: policy.created or policy.updated. Switch on this to route the event |
id | UUID | careCycle policy ID |
createdAt / updatedAt | ISO 8601 | When the policy was created / last updated |
customerId | UUID | The customer the policy belongs to |
policyType | enum | Product type, e.g. MA, MAPD, PDP, MS, ACA, Life, Annuity, LTC |
policySubType | string | Sub-type within the product family (e.g. HMO, PPO, Plan G) |
policyNumber / applicationId | string | Carrier policy number / application identifier |
carrierId | UUID | careCycle carrier ID (null if unresolved) |
carrierName | string | Insurance carrier name |
planName / planCode | string | Plan name and code (e.g. H1290-036-001) |
carrierAssignedPolicyId / healthSherpaPolicyId / sunFireEnrollmentCode | string | External identifiers from carrier and enrollment systems |
hiosId / metalLevel | string | ACA plan ID and metal tier (Bronze, Silver, Gold, Platinum, Catastrophic, Expanded Bronze) |
Status & dates
| Field | Type | Description |
|---|---|---|
status | enum | Policy status, e.g. Active, Placed, Pending, Suspended, Cancelled, Terminated, Future Cancel, Not Approved |
applicationApprovalDate / effectiveDate / terminationDate / renewalDate / enrollmentDate / cancelledDate | date | Key policy dates (YYYY-MM-DD) |
declineReason / declineReasonDescription | string | Why an application was declined (Not Approved) |
cancellationReason / cancellationReasonDescription | string | Why a policy was cancelled |
electionPeriod | enum | Enrollment period: IEP, AEP, OEP, SEP, ICEP, MA-OEP |
Enrollment & marketplace (ACA)
| Field | Type | Description |
|---|---|---|
gracePeriodStartDate / paidThroughDate | date | ACA effectuation dates |
ffmApplicationId / ffmSubscriberId | string | Federal marketplace identifiers |
exchangeStatus | enum | FFM, SBM, SBM FP, OFF EXCHANGE, PRIVATE EXCHANGE, UNKNOWN |
sepType / sepCode | string | Special Enrollment Period type and code |
sepStartDate / sepEndDate / sepDocumentationDate | date | SEP window and documentation dates |
sepDocumentationReceived | boolean | Whether SEP documentation has been received |
sepNotes | string | Free-text SEP notes |
Agent of record
| Field | Type | Description |
|---|---|---|
aorFirstName / aorLastName / aorNpn | string | Agent of record name and NPN |
writingAgentName / writingAgentNpn | string | Writing agent name and NPN |
Financial
| Field | Type | Description |
|---|---|---|
monthlyPremium / grossPremium / netPremium | decimal string | Premium amounts (gross is before subsidy, net after) |
deductible / outOfPocketMax | decimal string | Cost-sharing amounts |
subsidyAmount / usingSubsidy | decimal string / boolean | Subsidy amount and whether it's applied |
premiumMode | enum | Monthly, Quarterly, Semi-Annual, Annual |
paymentMode | enum | ACH, Credit/ debit card, Direct bill |
paymentMethod | enum | Credit Card, Debit Card, Check, ACH / Bank Draft, Money Order, Cash, Other |
initialCommission / renewalCommission / spifAmount | decimal string | Commission and incentive amounts |
Coverage details
| Field | Type | Description |
|---|---|---|
policyLives | integer | Number of people covered |
wasAgent | boolean | Whether an agent was involved in the enrollment |
writtenAs | enum | New Business, Like Plan Change, Unlike Plan Change, Reinstatement, Rewrite |
isReplacing / isRewrite | string / boolean | What the policy replaces, and whether it's a rewrite |
hospitalNetwork / pcpNetwork | string | Medicare network details |
ssbciVerificationRequired | boolean | Whether SSBCI (Special Supplemental Benefits for the Chronically Ill) verification is required, for MA/MAPD plans |
dailyBenefit / eliminationPeriod / benefitPeriod / hasCola | decimal string / integer / integer / boolean | Long-term care benefit details |
deathBenefit / term / maturityDate / riders | decimal string / integer / date / string | Life insurance details |
billingMethod / benefitReminder / surveyCompleted | string / date / boolean | Compliance and billing tracking |
reasonForPurchase / policyNotes | string | Free-text notes |
customer | object | The 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
| Field | Type | Description |
|---|---|---|
event_type | string | The webhook event, e.g. appointment.scheduled. Switch on this to route the event |
id | UUID | careCycle appointment ID (stable across the appointment's lifecycle) |
createdAt / updatedAt | ISO 8601 | When the appointment was created / last updated |
startTime / endTime | ISO 8601 | The scheduled window (UTC; use timezone to localize) |
timezone | string | IANA timezone the appointment was booked in (e.g. America/Chicago) |
status | enum | scheduled, confirmed, cancelled, completed, or no_show |
bookingSource | enum | How it was booked: ai_assistant, manual, or scheduling_page |
appointmentMode | enum | How 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 |
title | string | Human-readable appointment title |
location | string | Physical address for in_person meetings. in_person is not fully supported yet, so this is null in practice |
meetingUrl | string | Join URL for video_call meetings. video_call is not fully supported yet, so this is null in practice |
confirmedAt | ISO 8601 | When the appointment was confirmed (null until confirmed) |
cancelledAt | ISO 8601 | When the appointment was cancelled (null unless cancelled) |
cancellationReason | string | Why the appointment was cancelled (null unless cancelled) |
originCallId | UUID | The 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
| Field | Type | Description |
|---|---|---|
actor | object | Who performed the action. Always has a kind discriminator: user (a rep; userId, userName), customer (customerId), ai_assistant (callId, toolCallId), or system (reason) |
member | object | The team member the appointment is assigned to (id, name, email, npn, role, licensedStates), or null if unassigned |
campaign | object | The campaign the appointment belongs to (same shape as on call.completed), or null |
appointmentConfig | object | The appointment type it was booked under: id, name, appointmentLength (minutes), appointmentMode. null for older appointments that predate configs |
customer | object | The 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"
}| Field | Type | Description |
|---|---|---|
fromStartTime / toStartTime | ISO 8601 | The appointment's start time before and after the move |
fromEndTime / toEndTime | ISO 8601 | The 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"
}| Field | Type | Description |
|---|---|---|
reason | string | Why 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"
}| Field | Type | Description |
|---|---|---|
fromMemberId | UUID | The member the appointment was assigned to before (null if it was unassigned) |
toMemberId | UUID | The member it is now assigned to (null if it was unassigned) |