Skip to main content
Authenticated API

This endpoint requires a valid JWT Bearer token with integration_admin or manager roles. Accessible via the API gateway at /v1/integrations/*.

Payroll Integration API

Integrate with payroll providers, export timecards, and manage wage calculations.

Overview

AttributeValue
Base Path/api/v1/integrations/payroll
AuthenticationBearer Token
Required Rolesfinance_manager, hr_manager, restaurant_manager, manager, tenant_admin, platform_admin, system_admin, super_admin

Supported Providers

ProviderStatusFeatures
GustoSupportedFull sync, timecards, employees
ADPSupportedTimecards, employee sync
PaychexSupportedTimecards
Square PayrollSupportedFull sync
QuickBooks PayrollSupportedTimecards
Generic CSVSupportedManual export

Connection Management

List Connections

Get configured payroll integrations.

GET /api/v1/integrations/payroll/connections

Response

{
"data": [
{
"id": "conn_001",
"provider": "gusto",
"status": "connected",
"connected_at": "2025-06-01T00:00:00Z",
"last_sync": "2026-01-24T06:00:00Z",
"sync_status": "success",
"settings": {
"auto_sync_enabled": true,
"sync_frequency": "daily",
"include_tips": true
}
}
]
}

Connection Status Values

StatusDescription
connectedActive connection
disconnectedNeeds reconnection
errorConnection error
pendingSetup in progress

Connect Provider

Initiate connection to a payroll provider.

POST /api/v1/integrations/payroll/connections

Request Body

{
"provider": "gusto",
"redirect_uri": "https://app.example.com/payroll/callback"
}

Response

{
"connection_id": "conn_001",
"authorization_url": "https://gusto.com/oauth/authorize?...",
"expires_at": "2026-01-24T19:30:00Z"
}

Complete OAuth

Complete the OAuth flow.

POST /api/v1/integrations/payroll/connections/{connection_id}/callback

Request Body

{
"code": "oauth_code_from_provider",
"state": "state_token"
}

Disconnect Provider

DELETE /api/v1/integrations/payroll/connections/{connection_id}

Timecard Export

Export Timecards

Generate timecard export for payroll period.

POST /api/v1/integrations/payroll/timecards/export

Request Body

{
"connection_id": "conn_001",
"pay_period_start": "2026-01-01",
"pay_period_end": "2026-01-15",
"location_ids": ["loc_123", "loc_456"],
"include_tips": true,
"include_breaks": true
}

Response

{
"export_id": "exp_abc123",
"status": "processing",
"employee_count": 45,
"estimated_completion": "2026-01-24T19:05:00Z"
}

Get Export Status

GET /api/v1/integrations/payroll/timecards/export/{export_id}

Response

{
"export_id": "exp_abc123",
"status": "completed",
"provider": "gusto",
"pay_period": {
"start": "2026-01-01",
"end": "2026-01-15"
},
"summary": {
"employees": 45,
"total_regular_hours": 2850.5,
"total_overtime_hours": 125.0,
"total_tips": 4250.00,
"total_gross_wages": 48500.00
},
"employees": [
{
"employee_id": "emp_001",
"name": "John Smith",
"regular_hours": 80.0,
"overtime_hours": 5.0,
"tips": 125.00,
"gross_wages": 1450.00
}
],
"sync_result": {
"synced_at": "2026-01-24T19:05:00Z",
"records_sent": 45,
"records_accepted": 45,
"records_rejected": 0
}
}

Export Status Values

StatusDescription
processingExport in progress
completedExport successful
failedExport failed
partialSome records failed

Download CSV Export

Get timecard data as CSV file.

GET /api/v1/integrations/payroll/timecards/export/{export_id}/csv

Preview Export

Preview timecard data before syncing.

POST /api/v1/integrations/payroll/timecards/preview

Request Body

{
"pay_period_start": "2026-01-01",
"pay_period_end": "2026-01-15",
"location_ids": ["loc_123"]
}

Response

{
"preview": {
"employees": 45,
"total_hours": 2975.5,
"issues": [
{
"employee_id": "emp_023",
"name": "Jane Doe",
"issue": "missing_clock_out",
"date": "2026-01-10"
}
]
},
"warnings_count": 1
}

Employee Mapping

List Employee Mappings

GET /api/v1/integrations/payroll/employees

Response

{
"data": [
{
"id": "map_001",
"olympus_employee_id": "emp_001",
"olympus_name": "John Smith",
"provider_employee_id": "gusto_12345",
"provider_name": "John Smith",
"status": "mapped",
"last_synced": "2026-01-24T06:00:00Z"
},
{
"id": null,
"olympus_employee_id": "emp_002",
"olympus_name": "Jane Doe",
"provider_employee_id": null,
"status": "unmapped"
}
]
}

Map Employee

Link Olympus employee to payroll provider employee.

POST /api/v1/integrations/payroll/employees/map

Request Body

{
"olympus_employee_id": "emp_002",
"provider_employee_id": "gusto_12346"
}

Sync Employees

Sync employee data from payroll provider.

POST /api/v1/integrations/payroll/employees/sync

Wage Settings

Get Wage Rates

GET /api/v1/integrations/payroll/wages

Response

{
"settings": {
"overtime_threshold_weekly": 40,
"overtime_multiplier": 1.5,
"double_time_threshold": 12,
"double_time_multiplier": 2.0
},
"job_codes": [
{
"id": "job_server",
"name": "Server",
"hourly_rate": 15.00,
"tipped": true,
"tip_credit": 3.00
},
{
"id": "job_cook",
"name": "Line Cook",
"hourly_rate": 18.00,
"tipped": false
}
]
}

Update Wage Settings

PUT /api/v1/integrations/payroll/wages

Tip Distribution

Calculate Tip Distribution

Calculate tip pool distribution.

POST /api/v1/integrations/payroll/tips/calculate

Request Body

{
"date": "2026-01-24",
"location_id": "loc_123",
"tip_pool_type": "percentage",
"pool_rules": {
"server_share": 70,
"busser_share": 20,
"host_share": 10
}
}

Response

{
"date": "2026-01-24",
"total_tips": 1250.00,
"distribution": [
{
"employee_id": "emp_001",
"name": "Maria Server",
"role": "server",
"hours_worked": 8.0,
"direct_tips": 180.00,
"pool_share": 145.00,
"total_tips": 325.00
},
{
"employee_id": "emp_002",
"name": "Carlos Busser",
"role": "busser",
"hours_worked": 6.0,
"pool_share": 95.00,
"total_tips": 95.00
}
]
}

Get Tip Reports

GET /api/v1/integrations/payroll/tips/reports

Query Parameters

ParameterTypeDescription
start_datedateReport start
end_datedateReport end
location_iduuidFilter by location

Scheduled Syncs

Get Sync Schedule

GET /api/v1/integrations/payroll/connections/{connection_id}/schedule

Response

{
"enabled": true,
"frequency": "daily",
"time": "06:00",
"timezone": "America/Los_Angeles",
"next_sync": "2026-01-25T06:00:00Z",
"last_sync": {
"timestamp": "2026-01-24T06:00:00Z",
"status": "success",
"records_synced": 45
}
}

Update Sync Schedule

PUT /api/v1/integrations/payroll/connections/{connection_id}/schedule

Request Body

{
"enabled": true,
"frequency": "weekly",
"day_of_week": "monday",
"time": "06:00",
"timezone": "America/Los_Angeles"
}

Trigger Manual Sync

POST /api/v1/integrations/payroll/connections/{connection_id}/sync

Webhooks

EventDescription
payroll.sync_startedSync job started
payroll.sync_completedSync completed successfully
payroll.sync_failedSync failed
payroll.export_readyExport file ready
payroll.mapping_requiredNew employee needs mapping

Error Responses

StatusCodeDescription
400invalid_date_rangeDate range invalid
400missing_employee_mappingEmployees not mapped
401provider_auth_expiredNeed to reconnect
404connection_not_foundConnection ID not found
409sync_in_progressSync already running
502provider_errorPayroll provider error