Troubleshooting
Quick Diagnostic #
curl -i -X POST https://apiv2.audit1.com/api/v2/payroll/reports \
-H "X-Client-ID: audit1_test_cli_your_id_here" \
-H "X-Client-Secret: audit1_test_sec_your_secret_here" \
-H "Content-Type: application/json" \
-d '{
"employer_fein": "12-3456789",
"policy_number": "WC1025561",
"employees": [{
"first_name": "Test",
"last_name": "User",
"class_code": "8810",
"state": "CA",
"gross_wages": 2500,
"hours_worked": 80
}]
}'
Expected: HTTP/1.1 202 Accepted with JSON response.
Authentication Errors (401) #
"Missing authentication headers" #
Both X-Client-ID and X-Client-Secret are required on every request.
// ✗ Wrong — missing headers
fetch("https://apiv2.audit1.com/api/v2/payroll/reports", { method: "POST", body: data });
// ✓ Correct
fetch("https://apiv2.audit1.com/api/v2/payroll/reports", {
method: "POST",
headers: {
"X-Client-ID": process.env.AUDIT1_CLIENT_ID,
"X-Client-Secret": process.env.AUDIT1_CLIENT_SECRET,
"Content-Type": "application/json",
},
body: data,
});
Common mistakes:
- Using Authorization: Bearer instead (not how Audit1 auth works)
- Key truncated when copying from the portal
- Missing X-Client-Secret (both headers are required)
"Invalid client_id format" #
Client ID must start with the correct prefix:
✗ sk_test_abc123...
✗ audit1_abc123...
✓ audit1_test_cli_a1b2c3d4e5f6...
✓ audit1_live_cli_a1b2c3d4e5f6...
"Invalid client_id" / "Invalid client_secret" #
- Verify key exists and is active in your portal (Settings > Connections > API Keys)
- Check for extra spaces or newlines
- If you lost the secret → generate a new key (secrets can't be recovered)
Validation Errors (400) #
"Missing required fields" #
Three fields are required for payroll submission:
{
"employer_fein": "12-3456789", // ← required
"policy_number": "WC1025561", // ← required
"employees": [{ ... }] // ← required, non-empty
}
"employees must be non-empty" #
// ✗ Wrong
"employees": []
// ✓ Right — at least one employee
"employees": [{ "first_name": "Jane", "class_code": "8810", ... }]
"Invalid date format" #
Dates must be YYYY-MM-DD:
✗ 01/15/2024
✗ 15/01/2024
✗ 2024-1-15
✓ 2024-01-15
Not Found Errors (404) #
| Error | Check |
|---|---|
| "Employer not found" | FEIN format (accepts 12-3456789 or 123456789). Verify employer exists in Audit1. |
| "Policy not found" | Exact policy number (case-sensitive). Confirm policy is active. |
Connection Issues #
Wrong URL #
✓ https://apiv2.audit1.com/api/v2/payroll/reports
Info
There is no separate sandbox URL — same URL for both. Your API key prefix determines the environment.
Timeout #
Set a 30-second timeout. For 500+ employees, the API returns immediately with file_id: null and processes in the background.
Rate Limiting (429) #
async function requestWithRetry(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try { return await fn(); }
catch (e) {
if (e.status !== 429 || i === maxRetries - 1) throw e;
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000)); // 1s, 2s, 4s
}
}
}
Self-Diagnostic Checklist #
API Configuration
[ ] Base URL: https://apiv2.audit1.com/api/v1
[ ] X-Client-ID header present (audit1_test_cli_* or audit1_live_cli_*)
[ ] X-Client-Secret header present
[ ] Content-Type: application/json
Request Body
[ ] Valid JSON
[ ] employer_fein present
[ ] policy_number present
[ ] employees array with at least 1 entry
[ ] Dates as YYYY-MM-DD
[ ] Wages as positive numbers
Network
[ ] HTTPS connection
[ ] Firewall allows outbound HTTPS
[ ] Timeout set to 30+ seconds
MCP Agent Errors #
"Invalid or revoked API key" (code: -32001) #
Verify your Bearer token:
# Wrong — using REST API headers
-H "X-Client-ID: audit1_test_cli_..."
# Correct — MCP uses Bearer token
-H "Authorization: Bearer mcp_your_key_here"
- Check that the key starts with
mcp_followed by 64 hex characters - Verify the credential hasn't been revoked (ask your admin to check)
- Ensure no extra whitespace or newlines in the key
"Agent not authorized for this employer" (code: -32002) #
Your agent's scope doesn't include the requested employer:
- Provider agents: Verify the employer's
payroll_company_idsincludes your payroll company - Employer agents: You can only access your own employer ID
- Scope is checked fresh per request — if an employer was recently unlinked, access is revoked immediately
"Method not found" (code: -32601) #
✗ {"method": "tool/call", ...} ← typo
✗ {"method": "submit_payroll", ...} ← tool name, not method
✓ {"method": "tools/call", "params": {"name": "submit_payroll_data", ...}}
"Invalid params" (code: -32602) #
Missing required fields in your tool arguments:
// ✗ Missing employer_id
{"name": "list_employer_policies", "arguments": {}}
// ✓ Correct
{"name": "list_employer_policies", "arguments": {"employer_id": "681abc..."}}
Sandbox agent can't submit for real (code: -32003) #
Sandbox agents automatically force dry_run: true. To submit real data, create a non-sandbox agent credential.
Empty or unexpected tool response #
- Ensure you're parsing
result.content[0].text(MCP wraps tool results in content array) - Check that
employer_idandpolicy_idare valid ObjectId strings (24 hex characters) - Verify the policy is active (not expired or cancelled)
MCP docs
: See the full MCP Tools Reference for schemas and examples.
Still Stuck? #
Email support@audit1.com with:
- Your Client ID prefix (first 20 characters — never the full secret) or MCP key prefix (first 12 characters)
- The endpoint you're calling
- The full error response
- A sanitized example of your request body