# 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](#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 1. [Overview](#overview) 2. [Quick Start](#quick-start) 3. [Authentication](#authentication) 4. [Rate Limits](#rate-limits) 5. [Environments](#environments) 6. [SDKs & Libraries](#sdks--libraries) 7. [Support](#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: * **Employers**: [https://employer.audit1.info](https://employer.audit1.info) * **Payroll Companies**: [https://payrollcompany.audit1.info](https://payrollcompany.audit1.info) * **Carriers**: [https://carrier.audit1.info](https://carrier.audit1.info) 2. Navigate to **Dashboard** โ†’ **API 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) ```bash # 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): ```json { "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 * [Full API Reference](https://docs.audit1.info/api-reference) * [Integration Examples](https://docs.audit1.info/integration-examples) * [Webhook Setup](https://docs.audit1.info/webhooks-guide) *** ## 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 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**: * Employers: [https://employer.audit1.info](https://employer.audit1.info) * Payroll Companies: [https://payrollcompany.audit1.info](https://payrollcompany.audit1.info) * Carriers: [https://carrier.audit1.info](https://carrier.audit1.info) 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 ```bash # 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**: ```json { "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: ```json { "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 | 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**: ```javascript 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**: ```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**: ```bash 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: ```http X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 999 X-RateLimit-Reset: 1642291200 ``` ### Handling Rate Limits **Response when rate limited**: ```http 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**: ```javascript 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: ```javascript // 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 ```bash # โœ… 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: ```json { "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: ```javascript 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](https://status.audit1.com) 2. Review [Full API Reference](https://docs.audit1.info/api-reference) 3. Contact Support: [support@audit1.com](mailto:support@audit1.com) *** ## SDKs & Libraries ### Official SDKs #### Node.js SDK ```bash npm install @audit1/node-sdk ``` ```javascript 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 ```bash pip install audit1-python ``` ```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 ```bash composer require audit1/audit1-php ``` ```php '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): ```http GET /v1/policies?owner_id=emp_123&limit=25&starting_after=pol_456 ``` **Create Resource**: ```http POST /v1/policies Content-Type: application/json { "employer_id": "emp_1234567890", "effective_date": "2024-02-01T00:00:00.000Z" } ``` **Retrieve Resource**: ```http GET /v1/policies/pol_1234567890?owner_id=emp_1234567890 ``` **Update Resource**: ```http PATCH /v1/policies/pol_1234567890 Content-Type: application/json { "owner_id": "emp_1234567890", "premium": 1750.00 } ``` **Delete Resource**: ```http DELETE /v1/policies/pol_1234567890?owner_id=emp_1234567890 ``` *** ## Error Handling ### Error Response Format ```json { "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 ```javascript 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: ```javascript // 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 ```javascript 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](https://docs.audit1.com/api) * **Webhook Guide**: [webhooks-guide.md](webhooks-guide.md) * **API Keys Guide**: [api-keys-guide.md](api-keys-guide.md) ### Developer Support * **Email**: developer-support@audit1.com * **Response Time**: \< 4 hours (business hours) * **Discord**: [Audit1 Developers](https://discord.gg/audit1-dev) ### Status Page Monitor API uptime and incidents: * **Status Page**: [https://status.audit1.com](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 1. **[Create API Keys](api-keys-guide.md)** - Set up authentication 2. **[Configure Webhooks](webhooks-guide.md)** - Enable real-time events 3. **[Explore API Reference](https://docs.audit1.com/api)** - Detailed endpoint documentation 4. **[Join Developer Community](https://discord.gg/audit1-dev)** - Get help and share feedback *** *Ready to start building? Create your first API key and make your first call!*