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_ids includes 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_id and policy_id are 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