Troubleshooting

Common errors and how to fix them

🔧 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)

ErrorCheck
"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
📘

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/v2
  [ ] 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 [email protected] 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