API Usage
The REST API is the primary interface for Providers — organizations that integrate PayrollEngine into their HR landscape to deliver payroll as a service. Typical providers include EOR platforms, payroll bureaus, PEOs, and HCM/HRIS vendors.
The API follows RESTful conventions over HTTP/JSON. The OpenAPI specification (swagger.json) is included as a release artifact.
Getting Started
Swagger UI
The Swagger UI and OpenAPI endpoint are disabled by default. To enable Swagger, set EnableSwagger to true in appsettings.json:
{
"EnableSwagger": true
}
Swagger should remain disabled in production environments to avoid exposing the API specification publicly.
Base URL
All endpoints are relative to the configured base URL:
https://{host}:{port}/api/tenants/{tenantId}/...
Authentication
The backend supports three authentication modes, configured via Authentication in appsettings.json.
None (Default)
No authentication required. Suitable for development and testing.
API Key
Requests must include a valid API key. The key can also be provided via environment variable.
OAuth
Token-based authentication with the following settings:
| Setting | Description |
|---|---|
Authority |
OAuth authority URL (e.g. identity server) |
Audience |
Expected audience claim |
RequireHttpsMetadata |
Enforce HTTPS for metadata endpoint (default: true) |
ClientSecret |
Client secret for token validation |
The backend validates authority and audience on startup to prevent token confusion.
Tenant Isolation
To ensure multi-tenant capability, the backend supports the HTTP header Auth-Tenant. If the optional header is present, it is compared with the tenant of the URL for each REST request.
Auth-Tenant: "MyTenantIdentifier"
For example, the web application sets the Auth-Tenant HTTP header for all subsequent backend requests when the tenant is changed.
API Conventions
Endpoint Prefixes
| Prefix | Description | Example |
|---|---|---|
Query* |
Supports OData filter, order, select, and paging | QueryEmployees, QueryWageTypes |
Create* |
Creates a single object | CreateEmployee, CreateLookup |
CreateBulk* |
Creates multiple objects via bulk import | CreateBulkEmployees |
Get* |
Retrieves a single object by id | GetEmployee, GetPayrunJob |
Delete* |
Deletes a single object by id | DeleteEmployee, DeleteLookup |
Data Model Conventions
| Pattern | Description | Example |
|---|---|---|
*Set |
Composite object containing its child elements | LookupSet (lookup + lookup values), CaseSet (case + case fields + case values), PayrollResultSet (wage type, collector, and payrun results) |
*Invocation |
Request object that triggers a process | PayrunJobInvocation (starts a payrun job) |
Consolidated* |
Query or result that merges incremental values into a single view | ConsolidatedPayrunResultQuery |
The *Set pattern is used both for import (creating an object with all its children in a single request) and for export (retrieving a complete object tree). For example, CreateLookupSets creates a lookup including all its lookup values in one operation, which is significantly faster than creating the lookup and each value individually.
Name-Based References
PayrunJobInvocation uses name/identifier-based references instead of numeric ids. The required fields are PayrunName and UserIdentifier — the backend resolves these to internal ids.
Error Handling
The backend uses structured JSON error responses in production via UseExceptionHandler middleware.
Common HTTP Status Codes
| Status | Meaning |
|---|---|
| 200 | Success |
| 202 | Accepted (async payrun job enqueued) |
| 400 | Bad request (validation error) |
| 401 | Unauthorized (missing or invalid credentials) |
| 403 | Forbidden (tenant mismatch) |
| 404 | Resource not found |
| 422 | Unprocessable (e.g. retro triggered in preview mode) |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
See Also
- Data Querying — OData filter, order, select, and paging
- Payrun Jobs — payrun jobs, bulk operations, and security