Getting Started
Quick start guide for Audit1 Developer APIs
Getting Started with Audit1 Developer APIs
🚀 Quick Reference
| What You Need | Where to Find It | Time to First Call |
|---|---|---|
| API Key | Your Portal Dashboard → API Keys → Create | 2 minutes |
| Base URL | https://api.audit1.info/api/v1 | - |
| Test Key | Starts with audit1_test_sk_ | Sandbox data |
| Live Key | Starts with audit1_live_sk_ | Real data |
| First API Call | See 5-Minute Setup below | 5 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
5-Minute Setup
Get your first API call working in 5 minutes:
Step 1: Get Your API Key (2 min)
- Log into your Audit1 portal:
- Employers: https://employer.audit1.info
- Payroll Companies: https://payrollcompany.audit1.info
- Carriers: https://carrier.audit1.info
- Navigate to Dashboard → API Keys section
- Click Create API Key
- Select Sandbox environment
- 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 Goal | How Audit1 Helps | Typical KPI Lift |
|---|---|---|
| Reduce audit cycle time | Shared case file with webhook nudges when wage statements arrive | 25-40% faster close |
| Improve premium accuracy | Always-on payroll + class-code sync prevents exposure leakage | < 2% variance vs. manual |
| Expand PayGo programs | Standardized REST + Postman collections make new payroll partners live fast | Launch in 2-4 weeks |
| Strengthen compliance | Immutable audit trail + policy metadata exports for DOI / bureaus | Zero missing artifacts |
Adoption Checklist
- Map business milestones (e.g., annual audit, mid-term endorsement) to API resources.
- Assign data owners for payroll, employee, and policy entities to guarantee freshness.
- Define environments: sandbox for contract testing, production for live audits, optional staging for client pilots.
- Decide notification channels: webhooks for machines, Notification API or email for employer auditors / CSR teams.
- 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.
- Log in to your Audit1 portal:
- Employers: https://employer.audit1.info
- Payroll Companies: https://payrollcompany.audit1.info
- Carriers: https://carrier.audit1.info
- Navigate to Developer Settings → API Keys
- Click "Create new API key" with appropriate permissions
- 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).
- Go to Dashboard → Webhooks
- Add webhook URL (your endpoint that will receive events)
- Select events to receive (audit.completed, policy.updated, etc.)
- 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:
- Log in to your portal and navigate to Dashboard → API Keys
- Click "Create API Key"
- Choose environment (Production or Sandbox)
- Copy and securely store your key
API Key Format
| Environment | Key Prefix | Example |
|---|---|---|
| Production | audit1_live_sk_... | audit1_live_sk_abc123... |
| Sandbox | audit1_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
| Plan | Requests per Minute | Concurrent Webhooks |
|---|---|---|
| Starter | 100 | 5 |
| Professional | 1,000 | 25 |
| Enterprise | 10,000 | 100 |
Rate Limit Headers
Every API response includes rate limit information:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1642291200Handling 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:
| Aspect | Sandbox (audit1_test_sk_*) | Production (audit1_live_sk_*) |
|---|---|---|
| Base URL | https://api.audit1.info/api/v1 | https://api.audit1.info/api/v1 |
| Data | Test data, safe to experiment | Real business data |
| IDs | Prefixed with TEST_ | Production IDs |
| Processing | Faster (1-2 min) | Normal (5-10 min) |
| Webhooks | Delivered to test endpoints | Delivered to production endpoints |
| Rate Limits | More lenient | Standard 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:
- Check key starts with
audit1_test_sk_oraudit1_live_sk_ - Ensure no extra spaces in the Authorization header
- Verify key wasn't truncated when copying
- 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?
- Check API Status Page
- Review Full API Reference
- Contact Support: [email protected]
SDKs & Libraries
Official SDKs
Node.js SDK
npm install @audit1/node-sdkconst 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-pythonimport 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
| Language | Library | Maintainer |
|---|---|---|
| Go | audit1-go | @community |
| Ruby | audit1-ruby | @community |
| C#/.NET | Audit1.NET | @community |
| Java | audit1-java | @community |
API Endpoints Overview
Core Resources
| Resource | Endpoint | Description |
|---|---|---|
| Policies | /v1/policies | Insurance policy management |
| Employees | /v1/employees | Employee data and payroll |
| Payments | /v1/payments | Payment processing and history |
| Audits | /v1/audits | Audit management and reporting |
| Webhooks | /v1/webhooks | Event notification management |
| API Keys | /v1/api-keys | API key management |
Common Patterns
List Resources (with pagination):
GET /v1/policies?owner_id=emp_123&limit=25&starting_after=pol_456Create 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_1234567890Update 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_1234567890Error 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
| Type | Description | HTTP Status |
|---|---|---|
api_error | Server-side error | 500 |
authentication_error | Invalid API key | 401 |
invalid_request_error | Bad request format | 400 |
permission_error | Insufficient permissions | 403 |
rate_limit_error | Too many requests | 429 |
resource_not_found | Resource doesn't exist | 404 |
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
- API Reference: https://docs.audit1.com/api
- Webhook Guide: webhooks-guide.md
- API Keys Guide: api-keys-guide.md
Developer Support
- Email: [email protected]
- Response Time: < 4 hours (business hours)
- Discord: Audit1 Developers
Status Page
Monitor API uptime and incidents:
- Status Page: https://status.audit1.com
- Incident Notifications: Subscribe for email/SMS alerts
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
- Create API Keys - Set up authentication
- Configure Webhooks - Enable real-time events
- Explore API Reference - Detailed endpoint documentation
- Join Developer Community - Get help and share feedback
Ready to start building? Create your first API key and make your first call!
Updated 1 day ago
