API Reference
Complete reference for all Audit1 API endpoints
📖 API Reference
Base URL: https://apiv2.audit1.com/api/v2
📤 POST /payroll/reports
Submit payroll data for workers' compensation audit.
Required Fields
| Field | Type | Description |
|---|---|---|
employer_fein | string | Federal EIN ("12-3456789" or "123456789") |
policy_number | string | Workers' comp policy number |
employees | array | Non-empty array of employee records |
Optional Fields
| Field | Type | Description |
|---|---|---|
pay_period.start_date | string | Period start (YYYY-MM-DD) |
pay_period.end_date | string | Period end (YYYY-MM-DD) |
Employee Records
Flexible schema — include whatever payroll fields you have. Common fields:
| Field | Description |
|---|---|
first_name, last_name | Employee name |
employee_id | Your internal ID |
class_code | WC classification code (e.g., "8810") |
state | Work state (e.g., "CA") |
gross_wages | Gross wages for the period |
hours_worked | Hours worked |
overtime | Overtime pay |
Example Request
{
"employer_fein": "12-3456789",
"policy_number": "WC1025561",
"employees": [
{
"first_name": "Jane",
"last_name": "Smith",
"class_code": "8810",
"state": "CA",
"gross_wages": 2500.00,
"hours_worked": 80
}
],
"pay_period": {
"start_date": "2024-01-01",
"end_date": "2024-01-15"
}
}Response (202 Accepted)
{
"success": true,
"file_id": "682abc123def456789012345",
"status": "completed",
"environment": "sandbox",
"employer": {
"id": "681xyz789abc123456789012",
"business_name": "Smith Industries LLC",
"fein": "12-3456789"
},
"policy": {
"id": "680def456ghi789012345678",
"policy_number": "WC1025561"
},
"employee_count": 1,
"file_name": "Smith-Industries-LLC_2024-01-01_2024-01-15_WC1025561_..."
}
500+ employees: Returns immediately withfile_id: null. Processing continues in the background — check status via the endpoint below or your portal dashboard.
Errors
| Status | Error | Cause |
|---|---|---|
| 400 | Missing required fields | employer_fein, policy_number, or employees missing |
| 400 | employees must be non-empty | Empty employees array |
| 401 | Missing authentication headers | Missing X-Client-ID or X-Client-Secret |
| 401 | Invalid client_id | Key not found or deactivated |
| 401 | Invalid client_secret | Wrong secret for this client ID |
| 404 | Employer not found | No employer matches the FEIN |
| 404 | Policy not found | No active policy matches the number |
👥 POST /employees/sync
Report employee hires, terminations, and wage updates.
Required Fields
| Field | Type | Description |
|---|---|---|
employer_id | string | Employer identifier |
employees | array | Non-empty array of change records |
Each employee requires:
| Field | Type | Values |
|---|---|---|
employee_id | string | Your internal ID |
action | string | hire, terminate, or update |
Action-specific fields:
| Action | Required | Description |
|---|---|---|
hire | name, hire_date | New employee |
terminate | termination_date | Employee leaving |
update | (any fields) | Wage or info changes |
Example Request
{
"employer_id": "681xyz789abc123456789012",
"employees": [
{ "employee_id": "EMP001", "action": "hire", "name": "John Doe", "hire_date": "2024-01-15" },
{ "employee_id": "EMP002", "action": "terminate", "termination_date": "2024-03-01" },
{ "employee_id": "EMP003", "action": "update", "gross_wages": 3500.00 }
]
}Response (202 Accepted)
{
"message": "Employee sync initiated",
"sync_id": "682abc123def456789012345",
"file_id": "682abc123def456789012345",
"environment": "sandbox",
"employer_id": "681xyz789abc123456789012",
"employees_processed": 3,
"status": "processing"
}📋 GET /files/status/:file_id
Check processing status of a submitted file.
Path parameter: file_id — the ID returned from /payroll/reports or /employees/sync
Response (200)
{
"file_id": "682abc123def456789012345",
"status": "completed",
"created_at": "2026-03-28T10:30:00.000Z",
"updated_at": "2026-03-28T10:32:00.000Z",
"employee_count": 150,
"employer_id": "681xyz789abc123456789012",
"period": { "start": "2024-01-01", "end": "2024-01-15" }
}File Statuses
| Status | Description |
|---|---|
pending | ⏳ Received, waiting to process |
uploaded | 📥 Stored, beginning identification |
identified | 🔍 Employer and policy matched |
normalized | 📊 Data extracted and standardized |
validated | ✅ Class codes and states verified |
completed | 🎉 All processing finished |
failed | ❌ Processing failed |
🔔 POST /webhook/inbound/:connection_id
Push payroll data via webhook. Uses HMAC signature instead of API keys. See Webhooks for setup and signature details.
Body: Same format as /payroll/reports
Required headers:
| Header | Description |
|---|---|
X-Webhook-Signature | HMAC-SHA256(secret, "${timestamp}.${body}") hex digest |
X-Webhook-Timestamp | Unix milliseconds (within 5 min of server time) |
Response: Same shape as /payroll/reports
⚠️ Error Format
All errors return JSON:
{
"error": "Error type",
"message": "Human-readable description"
}| Status | Meaning | Action |
|---|---|---|
| 202 | ✅ Accepted | Success — processing |
| 400 | ❌ Bad Request | Check request body |
| 401 | 🔒 Unauthorized | Check credentials |
| 404 | 🔍 Not Found | Check IDs/FEIN |
| 500 | 💥 Server Error | Retry, then contact support |
| 502 | ⚡ Upstream Error | Retry |
💻 Client Libraries
JavaScript
class Audit1Client {
constructor(clientId, clientSecret) {
this.baseUrl = "https://apiv2.audit1.com/api/v2";
this.headers = {
"X-Client-ID": clientId,
"X-Client-Secret": clientSecret,
"Content-Type": "application/json",
};
}
async submitPayroll(employerFein, policyNumber, employees, payPeriod) {
const res = await fetch(`${this.baseUrl}/payroll/reports`, {
method: "POST",
headers: this.headers,
body: JSON.stringify({ employer_fein: employerFein, policy_number: policyNumber, employees, pay_period: payPeriod }),
});
if (!res.ok) throw new Error(`API Error (${res.status}): ${(await res.json()).error}`);
return res.json();
}
async syncEmployees(employerId, employees) {
const res = await fetch(`${this.baseUrl}/employees/sync`, {
method: "POST",
headers: this.headers,
body: JSON.stringify({ employer_id: employerId, employees }),
});
if (!res.ok) throw new Error(`API Error (${res.status}): ${(await res.json()).error}`);
return res.json();
}
async getFileStatus(fileId) {
const res = await fetch(`${this.baseUrl}/files/status/${fileId}`, { headers: this.headers });
if (!res.ok) throw new Error(`API Error (${res.status}): ${(await res.json()).error}`);
return res.json();
}
}
// Usage
const client = new Audit1Client(process.env.AUDIT1_CLIENT_ID, process.env.AUDIT1_CLIENT_SECRET);
const result = await client.submitPayroll("12-3456789", "WC1025561", [
{ first_name: "Jane", last_name: "Smith", class_code: "8810", state: "CA", gross_wages: 2500 }
], { start_date: "2024-01-01", end_date: "2024-01-15" });Python
import os, requests
class Audit1Client:
def __init__(self, client_id, client_secret):
self.base_url = "https://apiv2.audit1.com/api/v2"
self.headers = {"X-Client-ID": client_id, "X-Client-Secret": client_secret}
def submit_payroll(self, employer_fein, policy_number, employees, pay_period=None):
r = requests.post(f"{self.base_url}/payroll/reports", headers=self.headers,
json={"employer_fein": employer_fein, "policy_number": policy_number,
"employees": employees, "pay_period": pay_period}, timeout=30)
r.raise_for_status()
return r.json()
def sync_employees(self, employer_id, employees):
r = requests.post(f"{self.base_url}/employees/sync", headers=self.headers,
json={"employer_id": employer_id, "employees": employees}, timeout=30)
r.raise_for_status()
return r.json()
def get_file_status(self, file_id):
r = requests.get(f"{self.base_url}/files/status/{file_id}", headers=self.headers, timeout=30)
r.raise_for_status()
return r.json()
# Usage
client = Audit1Client(os.environ["AUDIT1_CLIENT_ID"], os.environ["AUDIT1_CLIENT_SECRET"])
result = client.submit_payroll("12-3456789", "WC1025561", [
{"first_name": "Jane", "last_name": "Smith", "class_code": "8810", "state": "CA", "gross_wages": 2500}
], {"start_date": "2024-01-01", "end_date": "2024-01-15"})Updated 1 day ago
