Authentication
API keys, environments, and HMAC signing
🔑 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/jsonCreating API Keys
- Log into your portal:
- 🏢 Employers: employer.audit1.info
- 📊 Payroll Companies: payrollcompany.audit1.info
- 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
API keys can be created for employers, payroll companies, carriers, and software companies.
🌐 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;🔐 HMAC Request Signing (Optional)
For extra security, sign requests with HMAC-SHA256. This prevents replay attacks and request tampering.
Additional Headers
X-Signature: a1b2c3d4e5f6...
X-Timestamp: 1704538800000How 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 |
Updated 1 day ago
