This is the only write endpoint in the API. Every other endpoint in this reference is a read-only
GET, and the API key you use for those will not work here — see Authentication below.Endpoint
Authentication
Authenticate with your API key in theX-Api-Key header, as everywhere else in this API. The key must carry the employees:write scope.
Keys created on the API keys page are read-only and are rejected here with 403. The key for this endpoint is issued separately, when you connect the REST API integration on the Integrations page.
How an Import Is Applied
1
Honestly validates the request
The whole body is checked against the schema below. If anything is malformed you get a
400 and nothing is queued.2
You get a 202 and an import id
A workforce import is far too much work for one HTTP request, so it runs in the background. The response confirms the import was accepted, not that it finished.
3
Honestly reconciles your account
Employees are created and updated one by one, supervisors are resolved once every employee has been applied, and anyone this API created but you no longer send is offboarded.
The result of an import appears on the Integrations page in the app, and account admins are emailed if any employee was skipped. There is no endpoint to poll for the outcome, so
import_uuid is a reference for support rather than something to check.Omitted, Null, and a Value
This is the part worth reading twice. Every optional property has three distinguishable states, and the difference between the first two is the difference between preserving a field and wiping it.attributes follows the same rule per entry, with membership of the list standing in for the property being present:
Location is cleared, Cost Center is set, and any attribute not in the list — Department, say — is left exactly as it is. An empty list therefore means “I have nothing to say about this employee’s attributes”, not “remove them all”.
Body Parameters
object[]
required
The complete set of employees to hold for this account. At least one.There is deliberately no limit on how many employees you send: reconciliation is only sound when one request carries your whole workforce, so an account of any size sends a single request. The only ceiling is the request body size we accept. Payloads of this shape compress extremely well, since most of their bytes are repeated attribute names — send
Content-Encoding: gzip.Age Category and Seniority
Two attribute names are special, because Honestly stores a bucket rather than what you send. Send the year — not a date, and not the bucket.
The bucket is derived at import time, which means these two drift as people age and accrue tenure. Sending the same year on every import is correct and intended — it is what keeps the bucket current. A value that is not exactly four digits skips that employee.
Offboarding
An employee this API created and you stop sending is offboarded on the next import. Employees created any other way — in the app, by a file upload, over SFTP, or by an HCM connector — are never touched by this endpoint. To protect you against a broken export, an import that would offboard more than the deletion threshold configured on the integration is cancelled in full and changes nothing at all. The threshold defaults to 20% of the employees this API manages, and you can change it in the REST API dialog on the Integrations page. Raise it deliberately for a planned mass offboarding, then set it back. The guard does not apply when nothing would be offboarded, so your first import into an empty account is never blocked.Example Request
workforce.json:
role and no permissions, so whatever an admin configured for him in the app stays exactly as it is. Iris left the management track: her supervisor and role are reset, her Location is cleared, and her Age Category is untouched because it is not in her list.
Example Response
string
Identifier of the queued import, returned with
202 Accepted. Keep it if you need to reference the import when contacting support.Errors
Errors use the same envelope as the rest of the API — see Error handling.
When One Employee Is Refused
Some problems affect a single employee rather than the whole request. That employee is skipped, the rest of the import is applied, and account admins are emailed a summary. An employee is skipped when:- their
roleis not one of the five accepted values - their
languageis not a valid ISO 639-1 code - their
Age CategoryorSeniorityis not exactly four digits - they list the same attribute twice
- their
emailalready belongs to somebody else
import_id, and the same import_id appearing twice.