Authentication
Every API request requires a Client ID and Client Secret sent as headers.
API Key Format #
Client ID: audit1_{env}_cli_{32chars}
Client Secret: audit1_{env}_sec_{32chars}
| Environment | Client ID Prefix | Client Secret Prefix |
|---|---|---|
| Sandbox | audit1_test_cli_ |
audit1_test_sec_ |
| Production | audit1_live_cli_ |
audit1_live_sec_ |
Required Headers #
X-Client-ID: audit1_test_cli_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4
X-Client-Secret: audit1_test_sec_f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3
Content-Type: application/json
Creating API Keys #
- Log into your portal:
- Employers: employer.audit1.info
- Payroll Companies: provider.audit1.com
- Go to Settings > Connections > Set Up Connection > API Keys
- Choose New API v2.0 > Generate API Credentials
- Copy both values — the Client Secret is shown only once
Info
API keys can be created for employers, payroll companies, carriers, and software companies.
Key Scope #
Every API key is created with a scope that restricts which APIs it can call:
| Scope | What it unlocks |
|---|---|
payroll |
Payroll reports, file status, employee sync, webhooks (default) |
payments |
Payment Links, ACH, bank accounts, payment webhooks |
all |
Both surfaces |
Calls to an endpoint outside your key's scope return 401 Unauthorized. Issue separate keys per workload — never reuse a payments-scoped key on payroll endpoints and vice versa.
Environments #
Both sandbox and production use the same URL. Your key prefix determines the environment automatically.
https://apiv2.audit1.com/api/v2
| Sandbox | Production | |
|---|---|---|
| Data | Isolated test data | Real business data |
| Processing | Faster (1-2 min) | Normal (5-10 min) |
| Billing | No charges | Standard billing |
| Switching | Just swap the API key — no code changes needed |
// Environment is determined by your key prefix — no code changes
const clientId = process.env.AUDIT1_CLIENT_ID; // test or live
const clientSecret = process.env.AUDIT1_CLIENT_SECRET;
Signed Requests (Optional HMAC) #
For extra security, sign requests with HMAC-SHA256. This prevents replay attacks and request tampering.
Additional Headers #
X-Signature: a1b2c3d4e5f6...
X-Timestamp: 1704538800000
How to Compute #
payload = "${timestamp}.${method}.${path}.${body}"
signature = HMAC-SHA256(client_secret, payload)
timestamp: Unix milliseconds (must be within 5 minutes of server time)method: HTTP method (POST,GET)path: Request path (/api/v2/payroll/reports)body: Raw request body (empty string for GET)
JavaScript #
const crypto = require("crypto");
function signRequest(clientSecret, method, path, body) {
const timestamp = Date.now().toString();
const payload = `${timestamp}.${method}.${path}.${body}`;
const signature = crypto
.createHmac("sha256", clientSecret)
.update(payload)
.digest("hex");
return { "X-Signature": signature, "X-Timestamp": timestamp };
}
Python #
import hmac, hashlib, time
def sign_request(client_secret, method, path, body):
timestamp = str(int(time.time() * 1000))
payload = f"{timestamp}.{method}.{path}.{body}"
signature = hmac.new(
client_secret.encode(), payload.encode(), hashlib.sha256
).hexdigest()
return {"X-Signature": signature, "X-Timestamp": timestamp}
️ Key Management Best Practices #
| ✓ Do | ✗ Don't |
|---|---|
| Store secrets in environment variables or a secrets manager | Hardcode secrets in source code |
| Use separate keys for sandbox and production | Reuse keys across environments |
| Rotate keys every 90 days | Leave unused keys active |
| Revoke immediately if compromised | Share secrets via email or Slack |
| Call from backend servers only | Expose secrets in browser-side code |
| Label keys descriptively (e.g., "Prod - Payroll Integration") | Store secrets in plain text files |
Audit Logging #
Every API request is logged with: request ID, client ID, timestamp, HTTP method/path, response status, response time, and signature validation result.
View logs in your portal under Developer > API Usage.
| Retention | Duration |
|---|---|
| Sandbox | 30 days |
| Production | 1 year |