Eligibility via REST API
Use the Eligibility Management API to keep your employee roster in sync with Wellhub so onboarding and offboarding stay up to date. The API follows REST conventions and uses JSON for all requests and responses, where the latter follow standard HTTP status codes to distinguish success and error scenarios.
For information about BASE_URL and ACCESS_TOKEN values, see Getting Started with the REST API. For an overview of Eligibility Identifiers and Entity Types, see Entity Types.
Endpoints summary
| Endpoint | Description |
|---|---|
| POST /v1/eligibility/jobs | Endpoint to create a job. |
| POST /v1/eligibility/jobs/{job-id}/items | Endpoint to create job items. |
| GET /v1/eligibility/jobs/{job-id}/items | Endpoint to list the job items. |
| POST /v1/eligibility/jobs/{job-id}/submit | Endpoint to submit a job. |
| GET /v1/eligibility/jobs/{job-id}/status | Endpoint to retrieve the job status. |
| GET /v1/eligibility/jobs/{job-id}/errors | Endpoint to list the job errors. |
| GET /v1/employees | Endpoint to list eligibles for a single entity. |
| GET /v1/companies/{company-tax-id}/employees | Endpoint to list eligibles for multi entities and channel partners. |
| GET /v1/companies | Endpoint to list entity companies. |
Eligibility jobs
Eligibility jobs are used to create, submit, and track batches of eligibility updates.
Create Job
Create a new eligibility job and return a job identifier for subsequent operations.
Curl example
curl -X POST "{{BASE_URL}}/v1/eligibility/jobs" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}"
Parameters
This endpoint does not define parameters.
Headers
| Name | Required | Description |
|---|---|---|
| Authorization | Yes | Authentication token used to authorize requests. |
Response codes
| Code | Description |
|---|---|
| 201 | Created |
| 401 | Unauthorized |
| 403 | Forbidden |
| 500 | Internal Server Error |
Example response
201 Created
{
"id": "152f4e34-da90-4c9c-9867-9280952a6b68"
}
Create Job Items
These items are employees' operations, which can create, update or delete entries on Wellhub's database.
For multi entities and channel partners: To get more clarity on the company tax IDs within your group, use the list entity companies endpoint.
Curl example
curl -X POST "{{BASE_URL}}/v1/eligibility/jobs/{{job-id}}/items" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}" \
-H "Content-Type: application/json" \
-d '[
{
"operation": "CREATE",
"company_tax_id": "1234567890",
"employee_id": "E-1029",
"full_name": "Maria Santos",
"email": "maria.santos@acme.com",
"national_id": "12345678901",
"department": "People",
"cost_center": "CC-001",
"office_zip_code": "12345",
"eligible_to_payroll": true,
"custom_fields": {
"location": "Sao Paulo"
}
}
]'
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| job-id | Path | Yes | Job ID. |
Request Payload Structure
The request body must be an array of job item objects, with maximum size of 500 items per request. Each object in the array represents an employee operation and supports the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
| operation | string | Yes | The action to perform: CREATE, UPDATE, or DELETE |
| company_tax_id | string | Yes | Identifies to which company an employee belongs |
| employee_id | string | Yes* | Employee identifier within company's system |
| full_name | string | No | Full name of the employee |
| string | Yes* | Email address of the employee. | |
| national_id | string | Yes* | National identification registry of the employee |
| department | string | No | Department where the employee works |
| cost_center | string | No | Cost center associated with the employee |
| office_zip_code | string | No | ZIP code of the employee's office location |
| eligible_to_payroll | boolean | No | Employee is allowed to use paycheck as a payment method |
| payroll_id | string | No | Employee identifier in company's payroll software |
| mobile_number | string | Yes* | Mobile phone number of the employee. |
| discount_subset_id | string | No | Identifier for the discount group applicable to the employee, when able. |
| custom_fields | object | No | Additional custom fields as key-value pairs. |
*Depending on the Eligibility Identifier defined in the company's contract with Wellhub, some of these fields may turn out to be optional. For example:
| Configuration | Required fields |
|---|---|
email | |
| Employee ID | employee_id |
| National ID | national_id |
| Employee ID and National ID | employee_id and national_id |
| Mobile Number | mobile_number |
All other identifier fields are optional for the configurations above.
For full details on how each identifier configuration works, see Eligibility Identifiers.
Contact your Wellhub integration representative if you are unsure which identifier applies to your contract.
Headers
| Name | Required | Description |
|---|---|---|
| Authorization | Yes | Authentication token used to authorize requests. |
| Content-Type | Yes | application/json. |
Response codes
| Code | Description |
|---|---|
| 204 | No Content |
| 400 | Bad Request (validation errors; see response body details) |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 413 | Content Too Large (request body exceeds 1 MB limit) |
| 500 | Internal Server Error |
Example request — CREATE
[
{
"operation": "CREATE",
"company_tax_id": "1234567890",
"employee_id": "E-1029",
"full_name": "Maria Santos",
"email": "maria.santos@acme.com",
"national_id": "12345678901",
"department": "People",
"cost_center": "CC-001",
"office_zip_code": "12345",
"eligible_to_payroll": true,
"custom_fields": {
"location": "Sao Paulo"
}
}
]
Example request — UPDATE
[
{
"operation": "UPDATE",
"company_tax_id": "1234567890",
"employee_id": "E-1029",
"full_name": "Maria Santos",
"email": "maria.santos@acme.com",
"national_id": "12345678901",
"department": "Engineering",
"cost_center": "CC-002",
"office_zip_code": "12345",
"eligible_to_payroll": true,
"payroll_id": "PAY-123",
"mobile_number": "+5511999999999",
"discount_subset_id": "1",
"custom_fields": {
"location": "Sao Paulo"
}
}
]
For UPDATE operations, any omitted field will be set to an empty value (""). To preserve an existing value, always include it explicitly in the request. The exception is eligible_to_payroll: its behavior when omitted depends on whether the company has payroll enabled. If payroll is not enabled, the field always defaults to false. If payroll is enabled, omitting the field preserves the existing value when one is already set, or defaults to true when no value has been set yet.
custom_fields behaves differently: only fields pre-configured by Wellhub for your company will be persisted or updated. To set up or modify your custom fields mapping, contact your Wellhub integration representative.
Example request — DELETE
[
{
"operation": "DELETE",
"company_tax_id": "1234567890",
"employee_id": "E-1029"
}
]
For DELETE operations, only the fields required to identify the employee (based on the eligibility identifier) and company_tax_id are needed. All other fields are ignored.
Example response
400 Bad Request
{
"message": "Bad Request",
"reason": "Bad information provided",
"errors": [
{
"field": "[0].operation",
"message": "must be one of CREATE, UPDATE, DELETE"
},
{
"field": "[0].company_tax_id",
"message": "cannot be blank"
}
]
}
List Job Items
List the items already attached to a job. Supports pagination via the cursor query parameter.
Pagination works as follows: when a response includes a non-null cursor field, pass that value as the cursor query parameter in the next request to retrieve the next page. When cursor is null, you have reached the last page. Do not construct or modify cursor values — treat them as opaque tokens.
Curl example
curl -X GET "{{BASE_URL}}/v1/eligibility/jobs/{{job-id}}/items?cursor={{cursor}}" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}" \
-H "Content-Type: application/json"
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| job-id | Path | Yes | Job ID. |
| cursor | Query | No | Cursor for pagination. |
Headers
| Name | Required | Description |
|---|---|---|
| Authorization | Yes | Authentication token used to authorize requests. |
Response codes
| Code | Description |
|---|---|
| 200 | OK |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 500 | Internal Server Error |
Example response
200 OK
{
"cursor": "next_cursor_token",
"data": [
{
"id": "item_1",
"job_id": "job_12345",
"change_number": 1,
"company_tax_id": "1234567890",
"cost_center": "CC-001",
"created_at": "2026-01-20T10:20:30Z",
"custom_fields": {
"location": "Sao Paulo"
},
"department": "People",
"discount_subset_id": "1",
"eligible_to_payroll": true,
"email": "maria.santos@acme.com",
"employee_id": "E-1029",
"full_name": "Maria Santos",
"mobile_number": "+5511999999999",
"national_id": "12345678901",
"office_zip_code": "12345",
"operation": "CREATE",
"payroll_id": "PAY-123"
}
]
}
Submit Job
Submit a job for processing once all items are uploaded.
Curl example
curl -X POST "{{BASE_URL}}/v1/eligibility/jobs/{{job-id}}/submit" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}"
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| job-id | Path | Yes | Job ID. |
Headers
| Name | Required | Description |
|---|---|---|
| Authorization | Yes | Authentication token used to authorize requests. |
Response codes
| Code | Description |
|---|---|
| 202 | Accepted |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 409 | Conflict |
| 422 | Unprocessable Entity |
| 500 | Internal Server Error |
Example response
No response body is returned for a successful request.
Get Job Status
Get the current processing status for a job.
Curl example
curl -X GET "{{BASE_URL}}/v1/eligibility/jobs/{{job-id}}/status" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}"
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| job-id | Path | Yes | Job ID. |
Headers
| Name | Required | Description |
|---|---|---|
| Authorization | Yes | Authentication token used to authorize requests. |
Response codes
| Code | Description |
|---|---|
| 200 | OK |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 500 | Internal Server Error |
Example response
200 OK
{
"id": "job_12345",
"status": "PROCESSING",
"updated_at": "2026-01-20T10:30:00Z",
"statistics": {
"newcomers": 10,
"updaters": 3,
"leavers": 2
}
}
Possible Job Status
Loading diagram...
| Status | Description |
|---|---|
| Draft | Job is in draft state and not yet submitted for validating. |
| Pending | Job is awaiting user action before processing. |
| Validating | Job is currently being validated and a change request is in progress; if not rejected, will be processed shortly. |
| Processing | Job is currently being processed. |
| Succeeded with errors | Job has been partially processed, with error entries that must be fixed. |
| Approval Requested | Job has a pending approval request by either Wellhub or the benefits manager due to extensive breaking changes in the eligible base. |
| Rejected | Job has been rejected. |
| Succeeded | Job was processed successfully. |
| Internal Server Error | A server-side error occurred during processing. It is recommended to try again. |
List Job Errors
List processing errors for a job. Supports pagination via the cursor query parameter.
Curl example
curl -X GET "{{BASE_URL}}/v1/eligibility/jobs/{{job-id}}/errors?cursor={{cursor}}" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}"
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| job-id | Path | Yes | Job ID. |
| cursor | Query | No | Cursor for pagination. |
Headers
| Name | Required | Description |
|---|---|---|
| Authorization | Yes | Authentication token used to authorize requests. |
Response codes
| Code | Description |
|---|---|
| 200 | OK |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 500 | Internal Server Error |
Example response
200 OK
{
"cursor": "next_cursor_token",
"data": [
{
"change_number": 1,
"field_name": "EMAIL",
"field_value": "invalid-email",
"error_type": "WRONG_FORMAT",
"recovered_by": null,
"company_tax_id": "1234567890"
},
{
"change_number": 2,
"field_name": "EMPLOYEE_ID",
"field_value": "E-1029",
"error_type": "CONFLICT",
"recovered_by": null,
"company_tax_id": "1234567890"
}
]
}
Response fields
| Field | Type | Description |
|---|---|---|
| change_number | integer | The sequential number of the item within the job that caused the error. |
| field_name | string | The name of the field that triggered the error. See Possible Error Details. |
| field_value | string | The value that was submitted for the field. |
| error_type | string | The type of error. See Possible Error Details. |
| recovered_by | string or null | If the error was automatically recovered, indicates the recovery method. null when not recovered. |
| company_tax_id | string | The company tax ID associated with the item that caused the error. |
Possible Error Details
The table below lists all possible field_name and error_type combinations that can be returned in the job errors response.
field_name | error_type | Description |
|---|---|---|
COMPANY_TAX_ID | INVALID_COMPANY_TAX_ID | The company tax ID does not match any valid company within the entity or group. |
EMAIL | MISSING | The email field is required based on the eligibility identifier but was not provided. |
EMAIL | WRONG_FORMAT | The email address is not in a valid format (expected: name@example.com). |
EMAIL | DUPLICATED | The same email address appears more than once in the job. |
EMAIL | DOMAIN_UNREACHABLE | The email domain could not be reached or verified. |
EMAIL | NOT_FOUND | The email does not match any existing eligible record. Applies to UPDATE and DELETE operations. |
EMAIL | CONFLICT | The email conflicts with an existing eligible record that belongs to a different employee. |
NATIONAL_ID | MISSING | The national ID field is required based on the eligibility identifier but was not provided. |
NATIONAL_ID | WRONG_FORMAT | The national ID is not in a valid format. |
NATIONAL_ID | DUPLICATED | The same national ID appears more than once in the job. |
NATIONAL_ID | NOT_FOUND | The national ID does not match any existing eligible record. Applies to UPDATE and DELETE operations. |
NATIONAL_ID | CONFLICT | The national ID conflicts with an existing eligible record that belongs to a different employee. |
EMPLOYEE_ID | MISSING | The employee ID field is required based on the eligibility identifier but was not provided. |
EMPLOYEE_ID | DUPLICATED | The same employee ID appears more than once in the job. |
EMPLOYEE_ID | NOT_FOUND | The employee ID does not match any existing eligible record. Applies to UPDATE and DELETE operations. |
EMPLOYEE_ID | CONFLICT | The employee ID conflicts with an existing eligible record that belongs to a different employee. |
MOBILE_NUMBER | MISSING | The mobile number field is required based on the eligibility identifier but was not provided. |
MOBILE_NUMBER | WRONG_FORMAT | The mobile number is not in a valid format. Must include the international country code (e.g., +1 999 999 9999). |
MOBILE_NUMBER | DUPLICATED | The same mobile number appears more than once in the job. |
MOBILE_NUMBER | NOT_FOUND | The mobile number does not match any existing eligible record. Applies to UPDATE and DELETE operations. |
MOBILE_NUMBER | CONFLICT | The mobile number conflicts with an existing eligible record that belongs to a different employee. |
DISCOUNT_SUBSET_ID | WRONG_FORMAT | The discount subset ID is not in a valid format. |
Employees
List Employees
List employees for a single entity. Supports pagination via the cursor query parameter.
Curl example
curl -X GET "{{BASE_URL}}/v1/employees?cursor={{cursor}}" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}"
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| cursor | Query | No | Cursor for pagination. |
Headers
| Name | Required | Description |
|---|---|---|
| Authorization | Yes | Authentication token used to authorize requests. |
Response codes
| Code | Description |
|---|---|
| 200 | OK |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 500 | Internal Server Error |
Example response
200 OK
{
"cursor": "next_cursor_token",
"data": [
{
"id": "emp_456",
"full_name": "John Doe",
"email": "john.doe@acme.com",
"employee_id": "E-2048",
"national_id": "10987654321",
"invitation_status": "ACTIVE",
"mobile_number": "+5511988888888",
"cost_center": "CC-001",
"department": "Engineering",
"office_zip_code": "20040-020",
"payroll_id": "PAY-2048",
"discount_subset_id": null,
"eligible_to_payroll": true,
"deleted_at": null,
"updated_at": "2026-01-20T11:00:00Z"
}
]
}
List Company's Employees
List employees for a specific company by tax ID. Supports pagination via the cursor query parameter.
Curl example
curl -X GET "{{BASE_URL}}/v1/companies/{{company-tax-id}}/employees?cursor={{cursor}}" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}"
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| company-tax-id | Path | Yes | Company Tax ID. |
| cursor | Query | No | Cursor for pagination. |
Note: due to the characteristics of the HTTP protocol, if the company-tax-id has any slash character(s), it must be sent without them.
Example: 00.623.904/0001-73 → 00623904000173 or 00.623.9040001-73
Headers
| Name | Required | Description |
|---|---|---|
| Authorization | Yes | Authentication token used to authorize requests. |
Response codes
| Code | Description |
|---|---|
| 200 | OK |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 500 | Internal Server Error |
Example response
200 OK
{
"cursor": "next_cursor_token",
"data": [
{
"id": "emp_123",
"full_name": "Maria Santos",
"email": "maria.santos@acme.com",
"employee_id": "E-1029",
"national_id": "12345678901",
"invitation_status": "INVITED",
"mobile_number": "+5511999999999",
"cost_center": "CC-001",
"department": "People",
"office_zip_code": "01310-100",
"payroll_id": "PAY-1029",
"discount_subset_id": null,
"eligible_to_payroll": false,
"deleted_at": null,
"updated_at": "2026-01-20T10:30:00Z"
}
]
}
Companies
List Entity Companies
If you are managing multiple companies or a channel partner organization, to facilitate eligibility management, you will be able to review the company tax ids under your structure.
List companies for the current entity. Supports pagination via the cursor query parameter.
Curl example
curl -X GET "{{BASE_URL}}/v1/companies?cursor={{cursor}}" \
-H "Authorization: Bearer {{ACCESS_TOKEN}}"
Parameters
| Name | In | Required | Description |
|---|---|---|---|
| cursor | Query | No | Cursor for pagination. |
Headers
| Name | Required | Description |
|---|---|---|
| Authorization | Yes | Authentication token used to authorize requests. |
Response codes
| Code | Description |
|---|---|
| 200 | OK |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 500 | Internal Server Error |
Example response
200 OK
{
"cursor": "next_cursor_token",
"data": [
{
"company_name": "Cool Company",
"company_tax_id": "1234567890"
}
]
}