Employee Enrolment
This guide walks you through enrolling an individual employee into a group’s health insurance using Enrolment Intents. You’ll learn how to create an intent, follow it through its lifecycle, handle the states that need your input, and confirm enrolment.
Before starting, ensure you’ve completed:
- Authentication: API key setup and idempotency
- Employer and employee management: syncing employers and employees
- Webhooks and events: receiving asynchronous updates
This guide assumes the employer already has an active group policy and the employee has been assigned to the group. See the Employer Health Insurance Setup guide to create the group policy first.
Overview
An enrolment intent represents the intention to enrol one employee into one group, and it tracks the status and progress of that enrolment from start to finish. It follows the same intent-based pattern as the rest of the Kota API: you create the intent, then react as Kota processes it asynchronously and advances it through a series of statuses.
Most of the work happens in the background. After you create an intent, Kota evaluates eligibility, talks to the insurance provider, and moves the intent through its lifecycle. Your integration reacts to those changes, either by subscribing to webhooks or by polling the intent.
Enrolment intents apply only to manual-enrolment groups. For API-only integrations, manual-enrolment groups should usually be your default choice because your integration controls when each employee is added to the group and enrolled.
Use automatic enrolment groups only when you are integrated with Embedded or Hosted and want Kota to automatically enrol all employees for a particular employer. For automatic enrolment groups, Kota handles the group addition and in some cases enrolment flows, so you don’t create enrolment intents yourself.
Lifecycle
Create enrolment intent represents the API call, not an observable status. After
creation, an intent generally starts in processing, unless the employee is not active
yet, in which case it starts in scheduled.
For this flow, the employee is ready once their employee status is active and they have
already been added to the group you are trying to enrol them into. Group membership is a
creation precondition: if the employee has not been added to the group, create the group
assignment first.
Statuses
The status field is the source of truth for where an intent is. Drive your integration
off it.
Status values, ineligibility reasons, and action codes are returned in snake_case. New
values may be added as Kota onboards providers, so handle unknown enum values gracefully
and prefer the human-readable reason fields when displaying information to end users.
Step 1: Create an enrolment intent
Create one intent per employee, per group. Only employee_id and group_id are
required.
Endpoint: POST /enrolment_intents
Request body:
force_confirmation is a rare option. Use it when your integration needs to guarantee
that the employee explicitly chooses whether to proceed before Kota enrols them. Each
provider has its own rules for when confirmation is required, and force_confirmation
lets you add this decision step even if the provider would normally allow enrolment to
continue without it.
desired_policy_start_date and enrolment_date answer different questions:
desired_policy_start_dateis the requested date for the policy to start. This date is subject to the employee’s employment date, the enrolment date, and provider-specific restrictions, so it is a preference rather than a guarantee.enrolment_dateis the date the enrolment selection was made. Set it when the employee or employer chose enrolment before your service submitted the intent to Kota, for example if there was a delay between the choice being made and your API call.
Response:
Send an Idempotency-Key on this POST. Retries with the same key won’t create a
duplicate intent, which is useful since creation kicks off asynchronous work. See
Idempotency.
Implementation notes:
The request is rejected with a 400/404 if a precondition isn’t met. Make sure that:
- the group exists, is
ready, and uses manual enrolment; - the employee exists under the same employer and has been added to the group;
- the employee is eligible for the group;
- there is no in-flight intent already for this employee + group (an intent counts as in-flight unless it’s
ineligibleornot_undertaken).
You do not need the employee to be active yet. If their start date is in the future,
the intent is created in scheduled status and processed automatically once they become
active. See API Errors for the error response shape.
Step 2: Track progress
After creation the intent advances on its own. Use webhooks to react to status changes. Don’t poll on a timer or assume how long a step takes.
How long an intent takes to move between statuses varies and is largely outside your control: eligibility checks, provider response times, and policy issuance can each take anywhere from seconds to several days depending on the insurer. Treat every transition as an asynchronous event. Subscribe to webhooks and act when they arrive, rather than polling on a fixed interval or building in time-based assumptions, which will either hammer the API or act on stale state. Reserve the retrieve/list endpoints for reconciliation and recovery (e.g. backfilling a missed webhook), not as your primary signal.
Webhooks (recommended)
Subscribe to the enrolment-intent events. Kota emits one per status transition. See Webhooks and events for delivery, retries, and signature verification.
Each payload identifies the intent so you can fetch its current state:
On receiving an event, call retrieve to read the authoritative state and any
status-specific detail (action_required, pending_confirmation, ineligibility_reason).
Retrieve or list (for reconciliation)
Use these to read the latest state on demand, after a webhook, or to catch up if one was missed. They aren’t a substitute for webhooks; don’t call them on a tight loop waiting for a transition.
Endpoint: GET /enrolment_intents/{enrolment_intent_id}
To reconcile in bulk, list and filter by employee_id, group_id, or one or more
status values (comma-separated):
Endpoint: GET /enrolment_intents
Step 3: Handle the states that need input
Depending on the plan and provider, the intent may pause and wait for you.
action_required
When status is action_required, the intent needs more information before it can
proceed (for example dependant or beneficiary details). Inspect action_required for
what’s needed and the deadline:
Collect and submit the required information. Once it’s complete, the intent advances automatically. Watch for the next status webhook.
The action payload tells you how to resolve the requirement. It always includes a code
and the information needed to complete the next step, such as adaptive requirement IDs,
coverage options, or details about dependant or other enrolment information that must be
collected. Depending on the action, your integration may resolve it through adaptive
requirements or by submitting the requested related data.
If due_by is present, treat it as the provider’s deadline for receiving the requested
information. Missing the deadline may negatively affect the policy start date, for
example by pushing the policy start further into the future than necessary.
ineligible
When status is ineligible, the employee can’t be enrolled. ineligibility_reason
explains why:
This is terminal for the intent. Resolve the underlying cause and create a new intent.
Prefer displaying the reason string to end users and treat code as a hint, with a
fallback for unrecognised values.
Ineligibility reasons are generally non-recoverable for the current intent. The main exception is when the employee is not active yet, which may be recoverable in some cases. When in doubt, show the human-readable reason, resolve the underlying issue if possible, and create a new intent.
Updating before enrolment
To change the policy configuration before enrolment completes, update the intent. This
resets it to processing and re-evaluates it. It’s not available once the intent is
enrolling, enrolled, or not_undertaken.
Endpoint: PUT /enrolment_intents/{enrolment_intent_id}
Step 4: Confirm enrolment
When status is pending_confirmation, the employee must explicitly agree before
enrolment proceeds. This happens for opt-in benefits, or whenever you created the intent
with force_confirmation: true.
Show the employee the intent’s disclosures and the pending_confirmation.reason first,
then confirm. See the Disclosures guide for how to retrieve and display disclosures.
Endpoint: POST /enrolment_intents/{enrolment_intent_id}/confirm
Confirming returns 204 No Content and moves the intent to enrolling.
Confirmation is a commitment to enrol the employee into the policy. Make sure the employee has reviewed the disclosures and explicitly agreed before calling this endpoint.
Step 5: Enrolment completes
Kota enrols the employee with the provider (enrolling). When the policy is issued the
intent becomes enrolled, you receive enrolment_intent.enrolled, and
policy_enrolments[].id (prefixed p_) is populated. No further action is needed.
policy_enrolments is an array because one enrolment intent can create more than one
policy. This can happen when the group is backed by a bundle of benefits instead of a
single benefit.
Webhooks summary
Handle these events to drive your UI:
Best practices
- React to webhooks, don’t poll or time it. Steps complete in variable time (seconds to days, depending on the insurer), so act on events as they arrive rather than polling on an interval or assuming a duration. Use retrieve/list only for reconciliation.
- Drive off
status, not assumptions. Re-fetch the intent when you receive a webhook and branch on the currentstatus; states can change between your reads. - Idempotency. Always send an
Idempotency-Keyon creation. - Display reasons, not codes. Use the
reason/reason_descriptionfields for end-user messaging and treat enumcodes as programmatic hints with a fallback. - Respect deadlines. Surface
due_byonaction_requiredandpending_confirmationso employees act in time.
Next steps
- Assign Employee to a Group: add employees to benefit groups before enrolment
- API Reference: Enrolment Intents: full endpoint and schema reference
- Webhooks and events: event handling
- API Errors: error response format
- Employer Health Insurance Setup: how groups and group policies are created

