Getting Started

Quick start guide for Audit1 Developer APIs

Getting Started with Audit1 Developer APIs

🚀 Quick Reference

What You NeedWhere to Find ItTime to First Call
API KeyYour Portal Dashboard → API Keys → Create2 minutes
Base URLhttps://api.audit1.info/api/v1-
Test KeyStarts with audit1_test_sk_Sandbox data
Live KeyStarts with audit1_live_sk_Real data
First API CallSee 5-Minute Setup below5 minutes
💡

Tip: Use test keys (audit1_test_sk_*) for development. They work against the same URL but with sandbox data.


Welcome

Welcome to Audit1's Developer Platform! Our APIs enable insurance carriers, payroll companies, and software providers to seamlessly integrate with Audit1's comprehensive audit and policy management system.

Table of Contents

  1. Overview
  2. Quick Start
  3. Authentication
  4. Rate Limits
  5. Environments
  6. SDKs & Libraries
  7. Support

5-Minute Setup

Get your first API call working in 5 minutes:

Step 1: Get Your API Key (2 min)

  1. Log into your Audit1 portal:
  2. Navigate to DashboardAPI Keys section
  3. Click Create API Key
  4. Select Sandbox environment
  5. Copy the key (starts with audit1_test_sk_)

⚠️ Important: Save your key immediately - it's only shown once!

Step 2: Make Your First Request (3 min)

# Replace YOUR_API_KEY with your actual key
curl -X POST https://api.audit1.info/api/v1/payroll/reports \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "employer_id": "EMP_TEST_001",
    "period_start": "2024-01-01",
    "period_end": "2024-03-31",
    "employees": [
      {
        "employee_id": "EE_001",
        "name": "Test Employee",
        "classification_code": "8810",
        "hours_worked": 520,
        "gross_wages": 26000
      }
    ],
    "payroll_data": {
      "total_payroll": 26000,
      "total_hours": 520,
      "officer_payroll": 0,
      "subcontractor_payments": 0
    }
  }'

Expected Response (202 Accepted):

{
  "message": "Payroll report submitted successfully",
  "report_id": "PR_TEST_1234567890",
  "status": "processing",
  "environment": "sandbox",
  "employee_count": 1,
  "estimated_processing_time": "1-2 minutes"
}

Success! Notice:

  • Report ID has TEST_ prefix (sandbox environment)
  • Processing time is faster (1-2 min vs 5-10 min in production)
  • No real data affected

Step 3: Explore More


Business Context

Audit1 sits in the middle of the workers' compensation premium audit loop. We connect carriers, payroll reporters, agencies, and employers around a single source of exposure truth, so policy audits, pay-as-you-go (PayGo) remittances, and compliance filings stay in sync. The Developer API exposes every touchpoint so partners can automate intake, class-code validation, audit scheduling, and endorsement billing without waiting for manual workflows.

Primary Personas

  • Carrier Audit + Compliance Teams: synchronize policy, premium, and audit adjustments to meet bureau (NCCI/independent bureau) expectations.
  • Payroll Platforms / Providers: stream approved payroll, job-class, and overtime data that powers exposure calculations and PayGo remittances.
  • Software Vendors / Third-Party Administrators: embed Audit1 carrier-grade workflows inside employer or broker portals to reduce rekeying.
  • Internal Audit Units: replace spreadsheets with automated follow-ups, request letters, and evidence capture aligned to workers' comp audit policies.

Value Narrative

Workers' Comp GoalHow Audit1 HelpsTypical KPI Lift
Reduce audit cycle timeShared case file with webhook nudges when wage statements arrive25-40% faster close
Improve premium accuracyAlways-on payroll + class-code sync prevents exposure leakage< 2% variance vs. manual
Expand PayGo programsStandardized REST + Postman collections make new payroll partners live fastLaunch in 2-4 weeks
Strengthen complianceImmutable audit trail + policy metadata exports for DOI / bureausZero missing artifacts

Adoption Checklist

  1. Map business milestones (e.g., annual audit, mid-term endorsement) to API resources.
  2. Assign data owners for payroll, employee, and policy entities to guarantee freshness.
  3. Define environments: sandbox for contract testing, production for live audits, optional staging for client pilots.
  4. Decide notification channels: webhooks for machines, Notification API or email for employer auditors / CSR teams.
  5. Document rollback plans (disable API key, pause webhook) for compliance sign-off.

Shared Responsibility Model

  • Audit1: uptime, data hosting, webhook delivery, API versioning, bureau-aligned schemas.
  • You: credential storage, request throttling, deduplication, payroll/PII governance per state rules.
  • Joint: incident response timelines, audit evidence retention, and schema migration rehearsals across carrier + payroll orgs.

Overview

What You Can Build

  • Policy Management Systems: Create, update, and manage insurance policies
  • Employee Data Sync: Real-time synchronization of employee information
  • Payment Processing: Integrate payment workflows and notifications
  • Audit Automation: Streamline audit processes and reporting
  • Custom Dashboards: Build tailored reporting and analytics interfaces

Key Features

  • RESTful APIs: Standard HTTP methods with JSON payloads
  • Real-time Webhooks: Instant notifications for important events
  • Sandbox Environment: Safe testing environment with test data
  • Comprehensive Documentation: Detailed guides and examples
  • Robust Security: API keys, webhook signatures, and HTTPS enforcement

Quick Start

Step 1: Get Your API Key

Important: API keys are created through your Audit1 portal dashboard (API Keys section), not programmatically via API.

  1. Log in to your Audit1 portal:
  2. Navigate to Developer Settings → API Keys
  3. Click "Create new API key" with appropriate permissions
  4. Copy and save your key securely (you won't see it again!)

Your API key will look like: audit1_live_sk_1234567890abcdef...

Step 2: Submit Your First Payroll Report

# Submit payroll data for workers' comp audit
curl -X POST https://api.audit1.info/api/v1/payroll/reports \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "employer_id": "EMP_12345",
    "period_start": "2024-01-01",
    "period_end": "2024-03-31",
    "employees": [
      {
        "employee_id": "EE_001",
        "name": "John Doe",
        "classification_code": "8810",
        "hours_worked": 520,
        "gross_wages": 15600
      }
    ],
    "payroll_data": {
      "total_payroll": 15600,
      "total_hours": 520,
      "officer_payroll": 0,
      "subcontractor_payments": 0
    }
  }'

Response:

{
  "message": "Payroll report submitted successfully",
  "report_id": "PR_1234567890",
  "status": "processing",
  "employer_id": "EMP_12345",
  "period": {
    "start": "2024-01-01",
    "end": "2024-03-31"
  },
  "employee_count": 1,
  "estimated_processing_time": "5-10 minutes"
}

Step 3: Configure Webhooks (Optional)

Important: Webhooks are configured through your Audit1 portal dashboard (Webhooks section), not programmatically via API.

Webhooks allow you to receive notifications from Audit1 when events occur (e.g., audit completed, policy updated).

  1. Go to Dashboard → Webhooks
  2. Add webhook URL (your endpoint that will receive events)
  3. Select events to receive (audit.completed, policy.updated, etc.)
  4. Test the webhook to verify it's working

Example webhook payload you'll receive:

{
  "event": "audit.completed",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "audit_id": "AUD_123",
    "employer_id": "EMP_12345",
    "status": "completed",
    "premium_calculated": 15234.50
  }
}

Authentication

Getting Your API Key

All API keys are created through the Audit1 Dashboard:

  1. Log in to your portal and navigate to Dashboard → API Keys
  2. Click "Create API Key"
  3. Choose environment (Production or Sandbox)
  4. Copy and securely store your key

API Key Format

EnvironmentKey PrefixExample
Productionaudit1_live_sk_...audit1_live_sk_abc123...
Sandboxaudit1_test_sk_...audit1_test_sk_xyz789...

Note: Both environments use the same base URL (https://api.audit1.info/api/v1). The API automatically routes to sandbox or production data based on your API key prefix.

Authentication Header

Include your API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Example Requests

JavaScript/Node.js:

const apiKey = 'audit1_live_sk_1234567890abcdef1234567890abcdef12';

const response = await fetch('https://api.audit1.info/api/v1/payroll/reports', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    employer_id: 'EMP_12345',
    period_start: '2024-01-01',
    period_end: '2024-03-31',
    employees: [...],
    payroll_data: {...}
  })
});

const data = await response.json();

Python:

import requests

api_key = 'audit1_live_sk_1234567890abcdef1234567890abcdef12'

headers = {
    'Authorization': f'Bearer {api_key}',
    'Content-Type': 'application/json'
}

payload = {
    'employer_id': 'EMP_12345',
    'period_start': '2024-01-01',
    'period_end': '2024-03-31',
    'employees': [...],
    'payroll_data': {...}
}

response = requests.post('https://api.audit1.info/api/v1/payroll/reports', 
                        headers=headers, 
                        json=payload)
data = response.json()

cURL:

curl -X GET https://api.audit1.info/api/v1/policies \
  -H "Authorization: Bearer audit1_live_sk_1234567890abcdef1234567890abcdef12" \
  -H "Content-Type: application/json"

Rate Limits

Current Limits

PlanRequests per MinuteConcurrent Webhooks
Starter1005
Professional1,00025
Enterprise10,000100

Rate Limit Headers

Every API response includes rate limit information:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1642291200

Handling Rate Limits

Response when rate limited:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json

{
  "error": {
    "type": "rate_limit_exceeded",
    "message": "Too many requests",
    "retry_after": 60
  }
}

Recommended retry logic:

async function apiCallWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      
      if (response.status === 429) {
        const retryAfter = parseInt(response.headers.get('Retry-After')) || 60;
        
        if (attempt < maxRetries) {
          await sleep(retryAfter * 1000);
          continue;
        }
      }
      
      return response;
    } catch (error) {
      if (attempt === maxRetries) throw error;
      await sleep(1000 * Math.pow(2, attempt)); // Exponential backoff
    }
  }
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

Environments

How It Works: Key-Based Environment Detection

Audit1 uses a single API URL for both sandbox and production. The environment is automatically detected from your API key prefix:

🔑 audit1_test_sk_abc123...  →  🧪 Sandbox Environment
🔑 audit1_live_sk_xyz789...  →  🚀 Production Environment

Same URL, Different Data:

AspectSandbox (audit1_test_sk_*)Production (audit1_live_sk_*)
Base URLhttps://api.audit1.info/api/v1https://api.audit1.info/api/v1
DataTest data, safe to experimentReal business data
IDsPrefixed with TEST_Production IDs
ProcessingFaster (1-2 min)Normal (5-10 min)
WebhooksDelivered to test endpointsDelivered to production endpoints
Rate LimitsMore lenientStandard limits apply

When to Use Each

🧪 Use Sandbox For:

  • Initial integration development
  • Testing error scenarios
  • Training new developers
  • Running automated tests
  • Validating webhook handling

🚀 Use Production For:

  • Live customer data
  • Real payroll processing
  • Actual audit workflows
  • Production deployments

Switching Environments

No code changes needed! Just swap the API key:

// Development
const apiKey = process.env.AUDIT1_TEST_KEY; // audit1_test_sk_...

// Production
const apiKey = process.env.AUDIT1_LIVE_KEY; // audit1_live_sk_...

💡 Pro Tip: Store both keys in your environment variables and switch via config.


Troubleshooting

Common Issues

❌ "Invalid API key" Error

Problem: 401 Unauthorized - Invalid API key

Solutions:

  1. Check key starts with audit1_test_sk_ or audit1_live_sk_
  2. Ensure no extra spaces in the Authorization header
  3. Verify key wasn't truncated when copying
  4. Check key is still active in Dashboard
# ✅ Correct
Authorization: Bearer audit1_test_sk_1234567890abcdef1234567890abcdef

# ❌ Wrong - extra spaces
Authorization: Bearer  audit1_test_sk_1234567890abcdef1234567890abcdef

# ❌ Wrong - missing "Bearer"
Authorization: audit1_test_sk_1234567890abcdef1234567890abcdef

❌ "Missing required fields" Error

Problem: 400 Bad Request - Missing required fields: employees

Solution: Ensure all required fields are present in your request body:

{
  "employer_id": "required",
  "period_start": "required (YYYY-MM-DD)",
  "period_end": "required (YYYY-MM-DD)",
  "employees": "required (array with at least 1 employee)",
  "payroll_data": "required (object with totals)"
}

❌ Rate Limit Exceeded

Problem: 429 Too Many Requests

Solution: Implement exponential backoff:

async function retryWithBackoff(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.status === 429 && i < maxRetries - 1) {
        const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
}

🔍 Debug Checklist

  • API key starts with correct prefix
  • Using Bearer token authentication
  • Content-Type header set to application/json
  • Request body is valid JSON
  • All required fields included
  • Date formats are YYYY-MM-DD
  • Testing against correct URL (https://api.audit1.info/api/v1)

Still Need Help?

  1. Check API Status Page
  2. Review Full API Reference
  3. Contact Support: [email protected]

SDKs & Libraries

Official SDKs

Node.js SDK

npm install @audit1/node-sdk
const Audit1 = require('@audit1/node-sdk');

const audit1 = new Audit1('audit1_live_sk_...');

// Create a policy
const policy = await audit1.policies.create({
  employer_id: 'emp_1234567890',
  effective_date: '2024-02-01T00:00:00.000Z',
  premium: 1500.00
});

// List employees
const employees = await audit1.employees.list({
  employer_id: 'emp_1234567890'
});

Python SDK

pip install audit1-python
import audit1

audit1.api_key = 'audit1_live_sk_...'

# Create a policy
policy = audit1.Policy.create(
    employer_id='emp_1234567890',
    effective_date='2024-02-01T00:00:00.000Z',
    premium=1500.00
)

# List employees
employees = audit1.Employee.list(
    employer_id='emp_1234567890'
)

PHP SDK

composer require audit1/audit1-php
<?php
require_once('vendor/autoload.php');

\Audit1\Audit1::setApiKey('audit1_live_sk_...');

// Create a policy
$policy = \Audit1\Policy::create([
    'employer_id' => 'emp_1234567890',
    'effective_date' => '2024-02-01T00:00:00.000Z',
    'premium' => 1500.00
]);

// List employees
$employees = \Audit1\Employee::all([
    'employer_id' => 'emp_1234567890'
]);
?>

Community Libraries

LanguageLibraryMaintainer
Goaudit1-go@community
Rubyaudit1-ruby@community
C#/.NETAudit1.NET@community
Javaaudit1-java@community

API Endpoints Overview

Core Resources

ResourceEndpointDescription
Policies/v1/policiesInsurance policy management
Employees/v1/employeesEmployee data and payroll
Payments/v1/paymentsPayment processing and history
Audits/v1/auditsAudit management and reporting
Webhooks/v1/webhooksEvent notification management
API Keys/v1/api-keysAPI key management

Common Patterns

List Resources (with pagination):

GET /v1/policies?owner_id=emp_123&limit=25&starting_after=pol_456

Create Resource:

POST /v1/policies
Content-Type: application/json

{
  "employer_id": "emp_1234567890",
  "effective_date": "2024-02-01T00:00:00.000Z"
}

Retrieve Resource:

GET /v1/policies/pol_1234567890?owner_id=emp_1234567890

Update Resource:

PATCH /v1/policies/pol_1234567890
Content-Type: application/json

{
  "owner_id": "emp_1234567890",
  "premium": 1750.00
}

Delete Resource:

DELETE /v1/policies/pol_1234567890?owner_id=emp_1234567890

Error Handling

Error Response Format

{
  "error": {
    "type": "invalid_request_error",
    "code": "missing_parameter",
    "message": "Missing required parameter: employer_id",
    "param": "employer_id",
    "request_id": "req_1234567890"
  }
}

Common Error Types

TypeDescriptionHTTP Status
api_errorServer-side error500
authentication_errorInvalid API key401
invalid_request_errorBad request format400
permission_errorInsufficient permissions403
rate_limit_errorToo many requests429
resource_not_foundResource doesn't exist404

Error Handling Best Practices

async function handleApiCall(apiCall) {
  try {
    const response = await apiCall();
    return response;
    
  } catch (error) {
    switch (error.type) {
      case 'authentication_error':
        // Check API key, refresh if needed
        console.error('Authentication failed:', error.message);
        break;
        
      case 'rate_limit_error': 
        // Implement exponential backoff
        const retryAfter = error.retry_after || 60;
        await sleep(retryAfter * 1000);
        return handleApiCall(apiCall); // Retry
        
      case 'resource_not_found':
        // Handle missing resource gracefully
        return null;
        
      default:
        // Log for investigation
        console.error('API error:', error);
        throw error;
    }
  }
}

Pagination

Standard Pagination

Most list endpoints support cursor-based pagination:

// Get first page
const firstPage = await audit1.policies.list({
  owner_id: 'emp_1234567890',
  limit: 25
});

// Get next page using last object's ID
if (firstPage.has_more) {
  const nextPage = await audit1.policies.list({
    owner_id: 'emp_1234567890',
    limit: 25,
    starting_after: firstPage.data[firstPage.data.length - 1].id
  });
}

Auto-Pagination Helper

async function* getAllPolicies(ownerId) {
  let startingAfter = null;
  
  do {
    const page = await audit1.policies.list({
      owner_id: ownerId,
      limit: 100,
      starting_after: startingAfter
    });
    
    for (const policy of page.data) {
      yield policy;
    }
    
    startingAfter = page.has_more ? 
      page.data[page.data.length - 1].id : null;
      
  } while (startingAfter);
}

// Usage
for await (const policy of getAllPolicies('emp_1234567890')) {
  console.log('Policy:', policy.policy_number);
}

Support

Documentation

Developer Support

Status Page

Monitor API uptime and incidents:

Common Questions

Q: Can I use the same API key for multiple applications? A: Yes, but we recommend separate keys for each application for better security and monitoring.

Q: How do I test webhooks locally? A: Use ngrok to expose your local server: ngrok http 3000

Q: What's the difference between owner_id and employer_id? A: owner_id is the entity that owns/manages the resource, while employer_id specifically refers to the employer in insurance contexts.

Q: Can I customize webhook retry behavior? A: Currently no, but this is on our roadmap. We retry for 24 hours with exponential backoff.

Q: Is there a GraphQL API? A: Not currently, but we're considering it based on developer feedback.


Next Steps

  1. Create API Keys - Set up authentication
  2. Configure Webhooks - Enable real-time events
  3. Explore API Reference - Detailed endpoint documentation
  4. Join Developer Community - Get help and share feedback

Ready to start building? Create your first API key and make your first call!