Employee Documents
Use the employee documents endpoints to store files against an employee record, such as a signed Form W-4, a Form I-9 or a general HR document. You can upload a document, list an employee's documents, download one, and delete one.
All endpoints require a bearer access token (see How to Get API Access).
Endpoints overview
| Method | Name | Endpoint |
|---|---|---|
| GET | List documents | https://api.worklio.com/wep/companies/{CLIENT_ID}/employees/{EMPLOYEE_ID}/documents |
| POST | Upload a document | https://api.worklio.com/wep/companies/{CLIENT_ID}/employees/{EMPLOYEE_ID}/documents |
| GET | Download a document | https://api.worklio.com/wep/files/{fileToken}/info, then the returned downloadUri. See Downloading Documents. |
| DELETE | Delete a document | https://api.worklio.com/wep/companies/{CLIENT_ID}/employees/{EMPLOYEE_ID}/documents/{DOCUMENT_ID} |
| Parameter | Type | Required | Description |
|---|---|---|---|
CLIENT_ID | integer | Yes | The company's id. Path parameter. |
EMPLOYEE_ID | integer | Yes | The employee's id. Path parameter. |
DOCUMENT_ID | integer | Yes (delete) | The id of the document, as returned by Upload a document or List documents. Path parameter. |
List employee documents
Returns the documents stored for an employee.
GET https://api.worklio.com/wep/companies/{CLIENT_ID}/employees/{EMPLOYEE_ID}/documents
This endpoint takes no request body.
Example request
require("dotenv").config();
const TOKEN = process.env.API_KEY;
const CLIENT_ID = process.env.CLIENT_ID;
const EMPLOYEE_ID = process.env.EMPLOYEE_ID;
const url = `https://api.worklio.com/wep/companies/${CLIENT_ID}/employees/${EMPLOYEE_ID}/documents`;
async function listEmployeeDocuments() {
const response = await fetch(url, {
method: "GET",
headers: {
accept: "application/json",
"api-version": "2.0",
authorization: `Bearer ${TOKEN}`,
"x-api-version": "2.0"
}
});
console.log(response.status);
console.log(await response.json());
}
listEmployeeDocuments();curl --request GET \
--url "https://api.worklio.com/wep/companies/$CLIENT_ID/employees/$EMPLOYEE_ID/documents" \
--header "accept: application/json" \
--header "api-version: 2.0" \
--header "authorization: Bearer $API_KEY" \
--header "x-api-version: 2.0"Example response
[
{
id: 142,
caption: 'Form W-9',
refId: 174,
docType:6 ,
fileToken: 'kx85lJPJkOvP_M7P0B8Hgcw8IhTEkVtHEyW_NcMocQ-NfvjcVC1jlCNyqSqwrhZ8s409qvsCgzI8xkSap_Ald8Dty4hLiEsmwQ4beVNqrkG_znA@@',
"note": "Employee changed from W-2 to 1099 contractor.",
clientSignatureRequired: false,
employeeSignatureRequired: false
}
]Upload a document
Uploads a file and attaches it to the employee. The request body is multipart/form-data. The maximum file size is 25MB.
POST https://api.worklio.com/wep/companies/{CLIENT_ID}/employees/{EMPLOYEE_ID}/documents
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
file | binary | Yes | The file to upload. |
caption | string | No | User-facing caption for the document. Maximum 100 characters. |
docType | integer (enum) | No | The document category. See Document type values. |
note | string | No | A note stored with the document. |
employeeAccess | integer (enum) | No | The access the employee has to the document. See Employee access values. |
Document type values
| Value | Name | Meaning |
|---|---|---|
1 | General | Generic document without a specialized tax-form workflow. |
2 | W4 | IRS Form W-4 employee withholding document. |
3 | I9 | Form I-9 employment eligibility verification document. |
4 | Form8850 | IRS Form 8850 pre-screening notice and certification request. |
5 | EnrollmentConfirmDoc | Enrollment confirmation document. |
6 | W9 | IRS Form W-9 taxpayer identification request. |
Employee access values
| Value | Name | Meaning |
|---|---|---|
0 | None | The employee cannot access the document. |
1 | Read | The employee can read the document. |
2 | Write | The employee can read and modify the document. |
Example request
This example uploads a PDF and gives the employee read access.
require("dotenv").config();
const fs = require("fs");
const path = require("path");
const TOKEN = process.env.API_KEY;
const CLIENT_ID = process.env.CLIENT_ID;
const EMPLOYEE_ID = process.env.EMPLOYEE_ID;
const url = `https://api.worklio.com/wep/companies/${CLIENT_ID}/employees/${EMPLOYEE_ID}/documents`;
const fileName = "W9-2026.pdf";
const filePath = path.join(__dirname, fileName);
async function uploadEmployeeDocument() {
const fileBuffer = fs.readFileSync(filePath);
const form = new FormData();
form.append("file", new Blob([fileBuffer], { type: "application/pdf" }), fileName);
form.append("caption", "Form W-9");
form.append("note", "Employee changed from W-2 to 1099 contractor.");
form.append("docType", "6");
form.append("employeeAccess", "1");
const response = await fetch(url, {
method: "POST",
headers: {
accept: "application/json",
"api-version": "2.0",
authorization: `Bearer ${TOKEN}`,
"x-api-version": "2.0"
},
body: form
});
console.log(response.status);
console.log(await response.json());
}
uploadEmployeeDocument();curl --request POST \
--url "https://api.worklio.com/wep/companies/$CLIENT_ID/employees/$EMPLOYEE_ID/documents" \
--header "accept: application/json" \
--header "api-version: 2.0" \
--header "authorization: Bearer $API_KEY" \
--header "x-api-version: 2.0" \
--form "[email protected];type=application/pdf" \
--form "caption=Form W-9" \
--form "note=Employee changed from W-2 to 1099 contractor." \
--form "docType=6" \
--form "employeeAccess=1"Do not set the content-type header yourself. Your HTTP client sets it, including the multipart boundary, when you pass a FormData body.
Example response
A successful upload returns 201.
{
"id": 142,
"caption": "Form W-9",
"refId": 174,
"docType": 6,
"fileToken": "Inj_iZ4knTu1Wi2kmRV-pJ9fvS8Njj88Y6wtdjYiljbc8mRXcvF5k22gyhhCdQJ_Ae4z@@",
"note": "Employee changed from W-2 to 1099 contractor.",
"clientSignatureRequired": false,
"employeeSignatureRequired": false
}The page was not displayed because the request entity is too large.Response fields
| Field | Type | Description |
|---|---|---|
id | integer | The document's id. Use it as DOCUMENT_ID to delete the document. |
caption | string | The caption you sent. |
refId | integer | Identifier of the entity that owns the document. For employee document endpoints this is the employee identifier. |
docType | integer (enum) | The document category. See Document type values. |
fileToken | string | Download token that clients can pass to file endpoints to retrieve the document binary. |
note | string | The note you sent. |
clientSignatureRequired | boolean | Indicates whether an additional client-side signature is still required. |
employeeSignatureRequired | boolean | Indicates whether an additional employee signature is still required. |
Download a document
Each document returned by List employee documents has a fileToken. Exchange it for a download link, then request the link. The flow is the same for every file in the API and is described in Downloading Documents.
Delete a document
Permanently deletes a document from the employee.
DELETE https://api.worklio.com/wep/companies/{CLIENT_ID}/employees/{EMPLOYEE_ID}/documents/{DOCUMENT_ID}
This endpoint takes no request body.
Example request
This example deletes document 142.
require("dotenv").config();
const TOKEN = process.env.API_KEY;
const CLIENT_ID = process.env.CLIENT_ID;
const EMPLOYEE_ID = process.env.EMPLOYEE_ID;
const DOCUMENT_ID = 142;
const url = `https://api.worklio.com/wep/companies/${CLIENT_ID}/employees/${EMPLOYEE_ID}/documents/${DOCUMENT_ID}`;
async function deleteEmployeeDocument() {
const response = await fetch(url, {
method: "DELETE",
headers: {
accept: "application/json",
"api-version": "2.0",
authorization: `Bearer ${TOKEN}`,
"x-api-version": "2.0"
}
});
console.log(response.status);
}
deleteEmployeeDocument();curl --request DELETE \
--url "https://api.worklio.com/wep/companies/$CLIENT_ID/employees/$EMPLOYEE_ID/documents/142" \
--header "accept: application/json" \
--header "api-version: 2.0" \
--header "authorization: Bearer $API_KEY" \
--header "x-api-version: 2.0" \
--includeExample response
A successful delete returns 204 with no response body. Don't parse the body. Parsing an empty body as JSON throws an error.
Updated about 6 hours ago
