Identify the company
Provide the AppyShift company name and portal slug, plus an authorized business contact and a technical contact.
AppyShift API · v1 · Public beta
Sync employees, schedules, time, credentials, organization data, and reports, then receive signed workforce events through one tenant-scoped API.
API access requires prior approval. Contact AppyShift Support to authorize your company and integration before requesting a token.
https://www.appyshift.com/{company_slug}
The AppyShift API is designed for server-to-server integrations. Every credential, token, workforce resource, report, and result is restricted to the company slug in the request URL.
The API is not self-service during public beta. An authorized company representative or integration partner must contact AppyShift Support and receive approval before credentials are provisioned.
{company_slug} with the client’s AppyShift portal slug.The documentation is public, but API credentials are issued only for approved company integrations. Send AppyShift Support enough context to review the request, confirm the company, and grant the smallest appropriate set of permissions.
Provide the AppyShift company name and portal slug, plus an authorized business contact and a technical contact.
Explain the system being connected, the business purpose, expected request volume, and whether webhooks or write access are needed.
List the resources and scopes required. Requests involving sensitive report fields receive an additional authorization review.
After approval, an AppyShift Super Admin provisions a named OAuth client and coordinates the one-time credential handoff.
AppyShift uses the OAuth 2.0 client-credentials grant for machine-to-machine API access. After Support approves the integration, an AppyShift Super Admin creates each named client for the company. Store the one-time secret in the calling system’s secret manager.
Client secrets are password-hashed and access tokens are SHA-256 hashed. Rotating a secret or revoking a client immediately invalidates its issued tokens.
See the token request and response exampleNeed credentials first? Request authorization from Support.
Once your intended integration is approved, connect it in four controlled steps.
Contact Support with the company, integration purpose, technical contact, and data access required.
An AppyShift Super Admin provisions a named client with approved scopes. Capture the one-time client secret securely.
Request a token, then call /api/v1/capabilities to confirm the tenant, expiry, scopes, and available operations.
Read workforce resources, run an approved report, perform permitted writes, or receive signed webhook events.
Continue to endpoint examplesEach endpoint keeps its request, response, and schema references together.
These rules apply across the protected REST API unless an endpoint documents a narrower limit or a different response field.
curl --request GET \
"https://www.appyshift.com/acme/api/v1/employees?limit=100" \
--header "Authorization: Bearer aps_oauth_xxx" \
--header "Accept: application/json"
{
"data": [
{"id": 42, "name": "Jordan Lee"}
],
"meta": {
"request_id": "req_7c85c8f31e0a",
"row_count": 1,
"pagination": {
"applied": true,
"limit": 100,
"has_more": false,
"next_after_id": null
}
}
}
Protected endpoints return UTF-8 JSON. Send Accept: application/json on reads and Content-Type: application/json for JSON writes. The OAuth token exchange is the form-encoded exception.
Accept: application/json Use the client-credentials grant from server-side code. Access tokens last up to 3,600 seconds, carry a granted scope subset, and must be replaced through /oauth/token rather than refreshed.
Authorization: Bearer {access_token} The company slug in the URL and the OAuth client tenant must agree. Credentials issued for one company cannot be used to cross into another company portal.
/{company_slug}/api/v1/... Protected success responses use data for resource output and meta for request context when applicable. Every protected API operation includes a request_id in its success metadata or error object.
meta.request_id Use each schema’s required and nullable flags. Dates use YYYY-MM-DD; timestamp and formatted report values follow the field-level contract rather than one inferred display format.
YYYY-MM-DD Omitted custom fields remain unchanged. Null or an empty scalar clears an optional custom field; required fields cannot be cleared. One request can submit at most 100 fields.
PATCH /employees/{id}/fields Pagination is endpoint-specific. The employee roster enables cursor mode with limit or after_id, returns at most 500 rows, and advertises has_more plus next_after_id in meta.pagination.
?limit=100&after_id=42 Protected errors return error.code, error.message, and error.request_id. OAuth token failures use the OAuth error and error_description shape instead.
error.request_id Per API client across its active access tokens
Per source IP within a company portal
Per minute and source IP
Maximum raw body accepted for an API write
HTTP 429 is the stable signal today. Use bounded exponential backoff with jitter; Retry-After and remaining-quota headers are not currently guaranteed.
| Operation | Policy | Guidance |
|---|---|---|
| GET resources and catalogs | Safe to retry | Repeat the same request after a temporary failure. Preserve filters and use the returned cursor for the next page. |
| POST /api/v1/reports/run | Read-only execution | A retry does not mutate workforce records, but it creates another access-log entry and consumes rate-limit capacity. |
| PATCH employee fields | Read back first | If the response is lost, retrieve the employee field values before retrying. Repeated writes can create additional audit activity. |
| Webhook deliveries | Deduplicate | Store X-AppyShift-Delivery as the idempotency key. REST writes do not currently accept a generic Idempotency-Key header. |
All API paths below are appended to the company-specific base URL.
/oauth/tokenExchange a client ID and one-time client secret for a short-lived bearer token.
curl --request POST \
https://www.appyshift.com/acme/oauth/token \
--user "aps_client_xxx:aps_secret_xxx" \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "scope=employee_fields:read reports:read reports:run"
{
"access_token": "aps_oauth_xxx",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "employee_fields:read reports:read reports:run"
}
/api/v1/capabilitiesReturns the current company, authentication type, granted scopes, expiry information, and only the operations this token can call.
curl \
https://www.appyshift.com/acme/api/v1/capabilities \
--header "Authorization: Bearer aps_oauth_xxx"
{
"data": {
"api_version": "v1",
"company_slug": "acme",
"client": {
"name": "Payroll warehouse",
"authentication": "oauth2",
"scopes": ["employees:read", "timesheets:read"],
"token_expires_at": "2026-08-20 16:30:00",
"client_expires_at": null
},
"operations": [
{"method": "GET", "path": "/api/v1/capabilities", "required_scopes": []},
{"method": "GET", "path": "/api/v1/employees", "required_scopes": ["employees:read"]},
{"method": "GET", "path": "/api/v1/timesheets", "required_scopes": ["timesheets:read"]}
]
},
"meta": {"request_id": "req_xxx", "operation_count": 3}
}
/api/v1/employeesReturns the employee roster with status, department, position, payroll identifier, and updated timestamp.
curl --get \
https://www.appyshift.com/acme/api/v1/employees \
--header "Authorization: Bearer aps_oauth_xxx" \
--data-urlencode "status=ACTIVE" \
--data-urlencode "updated_since=2026-08-01T00:00:00Z" \
--data-urlencode "limit=100"
{
"data": [
{
"id": 42,
"name": "Jordan Lee",
"email": "jordan.lee@example.com",
"payroll_id": "EE-1042",
"department_id": 7,
"department": "Front Desk",
"position_id": 12,
"job_title": "Guest Services Lead",
"pay_type": "HOURLY",
"status": "ACTIVE",
"active": true,
"updated_at": "2026-08-18 14:22:09"
}
],
"meta": {
"request_id": "req_xxx",
"row_count": 1,
"pagination": {
"applied": true,
"limit": 100,
"has_more": false,
"next_after_id": null
}
}
}
/api/v1/employees/{employee_id}Returns one employee’s standard non-sensitive profile and organization relationships.
curl \
https://www.appyshift.com/acme/api/v1/employees/42 \
--header "Authorization: Bearer aps_oauth_xxx"
{
"data": {
"id": 42,
"first_name": "Jordan",
"last_name": "Lee",
"preferred_name": "Jordy",
"name": "Jordan Lee",
"email": "jordan.lee@example.com",
"phone": "555-123-4567",
"status": "ACTIVE",
"employment_type": "FULL_TIME",
"department_id": 7,
"department": "Front Desk",
"position_id": 12,
"position": "Guest Services Lead",
"manager_id": 9,
"manager": "Morgan Ellis",
"hire_date": "2026-05-01",
"termination_date": "",
"location": "Main Office",
"payroll_id": "EE-1042",
"portal_enabled": true,
"created_at": "2026-04-20 09:13:00",
"updated_at": "2026-08-18 14:22:09"
},
"meta": {"request_id": "req_xxx"}
}
/api/v1/employees/{employee_id}/fieldsReturns selected reportable values using the same formats advertised by the employee-field catalog.
curl --get \
https://www.appyshift.com/acme/api/v1/employees/42/fields \
--header "Authorization: Bearer aps_oauth_xxx" \
--data-urlencode "fields=employee_name,hire_date,custom_17" \
--data-urlencode "formats[employee_name]=last_first" \
--data-urlencode "formats[hire_date]=us"
{
"data": {
"employee_id": 42,
"values": {
"employee_last_first": "Lee, Jordan",
"hire_date_us": "05/01/2026",
"custom_17": "Large"
}
},
"meta": {
"request_id": "req_xxx",
"field_count": 3,
"fields": [
{"field": "employee_name", "output_field": "employee_last_first", "label": "Employee", "format": "last_first", "sensitive": false},
{"field": "hire_date", "output_field": "hire_date_us", "label": "Hire Date", "format": "us", "sensitive": false},
{"field": "custom_17", "output_field": "custom_17", "label": "Uniform Size", "format": "default", "sensitive": false}
],
"sensitive_fields_included": false
}
}
/api/v1/employees/{employee_id}/fieldsPartially updates active, reportable custom fields. Omitted fields remain unchanged.
curl --request PATCH \
https://www.appyshift.com/acme/api/v1/employees/42/fields \
--header "Authorization: Bearer aps_oauth_xxx" \
--header "Content-Type: application/json" \
--data '{
"values": {
"custom_17": "Extra Large",
"custom_24": "2026-09-30",
"custom_31": true
}
}'
{
"data": {
"employee_id": 42,
"values": {
"custom_17": "Extra Large",
"custom_24": "2026-09-30",
"custom_31": "1"
}
},
"meta": {
"request_id": "req_xxx",
"changed_fields": ["custom_17", "custom_24", "custom_31"]
}
}
/api/v1/employees/{employee_id}/payroll-idAssigns or clears the external payroll identifier for one employee.
curl --request POST \
https://www.appyshift.com/acme/api/v1/employees/42/payroll-id \
--header "Authorization: Bearer aps_oauth_xxx" \
--header "Content-Type: application/json" \
--data '{"payroll_id":"EE-1042"}'
{
"data": {
"id": 42,
"name": "Jordan Lee",
"email": "jordan.lee@example.com",
"payroll_id": "EE-1042",
"active": true
},
"meta": {"request_id": "req_xxx"}
}
/api/v1/employee-fieldsReturns reportable system and custom field definitions, choice options, and supported output formats.
curl \
https://www.appyshift.com/acme/api/v1/employee-fields \
--header "Authorization: Bearer aps_oauth_xxx"
{
"data": [
{
"key": "employee_name",
"label": "Employee",
"group": "Identity",
"source": "system",
"type": "system",
"custom_field_id": null,
"writable": false,
"required": false,
"options": [],
"available_on_roster": true,
"sensitive": false,
"formats": [
{"key": "default", "label": "First Last", "output_field": "employee_name"},
{"key": "last_first", "label": "Last, First", "output_field": "employee_last_first"}
]
}
],
"meta": {
"request_id": "req_xxx",
"row_count": 1,
"sensitive_fields_included": false
}
}
/api/v1/timesheetsReturns completed clock-in and clock-out entries for a required date range.
curl --get \
https://www.appyshift.com/acme/api/v1/timesheets \
--header "Authorization: Bearer aps_oauth_xxx" \
--data-urlencode "start_date=2026-08-01" \
--data-urlencode "end_date=2026-08-14"
{
"data": [{
"id": 8221,
"employee_id": 42,
"employee_name": "Jordan Lee",
"employee_payroll_id": "EE-1042",
"work_date": "2026-08-03",
"clock_in": "2026-08-03 08:02:00",
"clock_out": "2026-08-03 16:31:00",
"hours": 8.0167,
"entry_type": "MOBILE",
"notes": ""
}],
"meta": {"request_id": "req_xxx", "start_date": "2026-08-01", "end_date": "2026-08-14", "row_count": 1}
}
/api/v1/schedulesReturns employee shift assignments, times, status, position, department, location, and notes for a required date range.
curl --get \
https://www.appyshift.com/acme/api/v1/schedules \
--header "Authorization: Bearer aps_oauth_xxx" \
--data-urlencode "start_date=2026-08-17" \
--data-urlencode "end_date=2026-08-23"
{
"data": [{
"id": 5512,
"employee_id": 42,
"employee_name": "Jordan Lee",
"employee_payroll_id": "EE-1042",
"shift_date": "2026-08-18",
"start_time": "08:00:00",
"end_time": "16:00:00",
"status": "PUBLISHED",
"location": "Main Office",
"notes": "",
"position_title": "Guest Services Lead",
"department_name": "Front Desk"
}],
"meta": {"request_id": "req_xxx", "start_date": "2026-08-17", "end_date": "2026-08-23", "row_count": 1}
}
/api/v1/time-offReturns time-off requests for a date range or employee leave balances for a year.
curl --get \
https://www.appyshift.com/acme/api/v1/time-off \
--header "Authorization: Bearer aps_oauth_xxx" \
--data-urlencode "view=requests" \
--data-urlencode "start_date=2026-08-01" \
--data-urlencode "end_date=2026-09-30" \
--data-urlencode "employee_id=42"
{
"data": [{
"id": 381,
"employee_id": 42,
"employee_name": "Jordan Lee",
"employee_payroll_id": "EE-1042",
"type": "VACATION",
"start_date": "2026-09-08",
"end_date": "2026-09-10",
"status": "APPROVED",
"reason": "Family trip",
"reviewed_at": "2026-08-20 11:10:00",
"review_notes": "Approved",
"created_at": "2026-08-19 09:25:00"
}],
"meta": {"request_id": "req_xxx", "view": "requests", "start_date": "2026-08-01", "end_date": "2026-09-30", "row_count": 1}
}
/api/v1/credentialsReturns employee certifications and licenses with issue, expiry, verification, and status information.
curl --get \
https://www.appyshift.com/acme/api/v1/credentials \
--header "Authorization: Bearer aps_oauth_xxx" \
--data-urlencode "status=ACTIVE" \
--data-urlencode "expiring_within_days=60"
{
"data": [{
"id": 91,
"employee_id": 42,
"employee_name": "Jordan Lee",
"employee_payroll_id": "EE-1042",
"certification_name": "Food Handler",
"credential_number": "FH-10293",
"issued_at": "2026-01-10",
"expires_at": "2027-01-10",
"status": "ACTIVE",
"notes": "",
"verified_at": "2026-01-11 10:00:00"
}],
"meta": {"request_id": "req_xxx", "row_count": 1}
}
/api/v1/departmentsReturns departments with descriptions, display colors, and active employee counts.
curl https://www.appyshift.com/acme/api/v1/departments \
--header "Authorization: Bearer aps_oauth_xxx"
{
"data": [{"id": 7, "name": "Front Desk", "description": "Guest arrival team", "color": "#2563eb", "employee_count": 12}],
"meta": {"request_id": "req_xxx", "row_count": 1}
}
/api/v1/positionsReturns job positions with descriptions, department names, and active employee counts.
curl https://www.appyshift.com/acme/api/v1/positions \
--header "Authorization: Bearer aps_oauth_xxx"
{
"data": [{"id": 12, "title": "Guest Services Lead", "description": "Leads guest arrival operations", "department_name": "Front Desk", "employee_count": 3}],
"meta": {"request_id": "req_xxx", "row_count": 1}
}
/api/v1/locationsReturns work-location addresses, coordinates, geofence settings, status, and active employee counts.
curl https://www.appyshift.com/acme/api/v1/locations \
--header "Authorization: Bearer aps_oauth_xxx"
{
"data": [{
"id": 3,
"name": "Main Office",
"address": "100 Main St",
"city": "Austin",
"state": "TX",
"zip": "78701",
"lat": 30.2672,
"lon": -97.7431,
"is_active": true,
"geofence_radius_feet": 500,
"employee_count": 18
}],
"meta": {"request_id": "req_xxx", "row_count": 1}
}
/api/v1/deductionsReturns active deduction elections, employee amounts, and employer matching values.
curl --get \
https://www.appyshift.com/acme/api/v1/deductions \
--header "Authorization: Bearer aps_oauth_xxx" \
--data-urlencode "employee_id=42"
{
"data": [{
"employee_id": 42,
"employee_name": "Jordan Lee",
"employee_payroll_id": "EE-1042",
"code": "MEDICAL",
"label": "Medical Plan",
"deduction_type": "PRE_TAX",
"employee_amount": 85.25,
"employer_match": 50
}],
"meta": {"request_id": "req_xxx", "row_count": 1}
}
/api/v1/reportsReturns saved report definitions and the datasets and columns available to the token.
curl \
https://www.appyshift.com/acme/api/v1/reports \
--header "Authorization: Bearer aps_oauth_xxx"
{
"data": [
{
"id": 18,
"name": "Active employee roster",
"description": "Current employees for payroll review",
"dataset": "employee_roster",
"columns": ["employee_name", "department", "hire_date"],
"column_formats": {"employee_name": "last_first", "hire_date": "us"},
"filters": {"status": "ACTIVE"},
"updated_at": "2026-08-18 11:45:00"
}
],
"datasets": {
"employee_roster": {
"label": "Employee roster",
"date_enabled": false,
"default_columns": ["employee_name", "department", "position"],
"columns": {
"employee_name": {"label": "Employee", "sensitive": false}
}
}
},
"meta": {
"request_id": "req_xxx",
"row_count": 1,
"sensitive_fields_included": false
}
}
/api/v1/reports/runRuns a saved report by report_id or an ad-hoc report using a dataset, columns, formats, labels, and filters.
curl --request POST \
https://www.appyshift.com/acme/api/v1/reports/run \
--header "Authorization: Bearer aps_oauth_xxx" \
--header "Content-Type: application/json" \
--data '{
"dataset": "employee_roster",
"columns": ["employee_name", "department", "hire_date"],
"column_formats": {
"employee_name": "last_first",
"hire_date": "us"
},
"filters": {"status": "ACTIVE"},
"metadata": {
"workflow_run_id": "sync_2026_08_19_001",
"destination": "payroll"
}
}'
{
"data": [
{
"employee_last_first": "Lee, Jordan",
"department": "Front Desk",
"hire_date_us": "05/01/2026"
}
],
"meta": {
"request_id": "req_xxx",
"report_id": null,
"dataset": "employee_roster",
"row_count": 1,
"columns": [
{"key": "employee_last_first", "label": "Employee"},
{"key": "department", "label": "Department"},
{"key": "hire_date_us", "label": "Hire Date"}
],
"sensitive_fields_included": false,
"client_metadata": {
"workflow_run_id": "sync_2026_08_19_001",
"destination": "payroll"
}
}
}
Subscribe an HTTPS endpoint to operational events such as schedule publication and time-off decisions. AppyShift sends an event envelope as JSON after the application change is committed.
Webhook registration is separate from OAuth API clients. A user with settings.integrations.manage can add the target URL, select event filters, attach a signing-secret credential, send a test event, and inspect or retry deliveries.
employee.createdA new employee profile is committed.
ViewEmployeeWebhookPayload
employee.updatedAn employee profile, status, termination, or reactivation is committed.
ViewEmployeeWebhookPayload
schedule.publishedA full or scoped weekly schedule publication changes the employee-visible schedule.
ViewSchedulePublishedWebhookPayload
pto.requestedAn employee, manager, or administrator submits a time-off request. The legacy pto name applies to every supported leave type.
ViewTimeOffRequestedWebhookPayload
pto.approvedA time-off request moves to approved from another status.
ViewTimeOffApprovedWebhookPayload
pto.deniedA time-off request moves to denied from another status.
ViewTimeOffDeniedWebhookPayload
pto.cancelledA manager or administrator moves a time-off request to cancelled.
ViewTimeOffCancelledWebhookPayload
time_entry.approvedA reviewed time entry moves to approved individually or in bulk.
ViewTimeEntryApprovedWebhookPayload
time_entry.rejectedA reviewed time entry moves to rejected individually or in bulk.
ViewTimeEntryRejectedWebhookPayload
shift_swap.approvedA shift swap or shift-board pickup is approved manually or automatically.
ViewShiftSwapApprovedWebhookPayload
shift_swap.rejectedA manager rejects a shift swap or shift-board pickup.
ViewShiftSwapRejectedWebhookPayload
onboarding.completedAn employee completes every currently available onboarding task.
ViewOnboardingCompletedWebhookPayload
payroll.exportedAn authorized user downloads the primary payroll export.
ViewPayrollExportedWebhookPayload
tip_pool.approvedA pending tip pool is approved individually or from the manager task inbox.
ViewTipPoolApprovedWebhookPayload
integration.testAn administrator queues a test event from Integrations Hub.
ViewIntegrationTestWebhookPayload
View the common WebhookEnvelope schema
| Header | Meaning |
|---|---|
Content-Type | application/json |
X-AppyShift-Event | Event name, matching the envelope's event property. |
X-AppyShift-Delivery | Stable delivery ID. Persist it as an idempotency key so a retry does not apply the event twice. |
X-AppyShift-Timestamp | Unix timestamp included when a signing credential is attached. |
X-AppyShift-Signature | sha256= followed by the lowercase HMAC-SHA256 signature. |
2xx status after safely accepting the event. Other responses are treated as delivery failures.Compute the HMAC over the exact timestamp header, a period, and the unmodified request body. Compare signatures with a constant-time function before parsing or processing the event.
$rawBody = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_APPYSHIFT_TIMESTAMP'] ?? '';
$received = $_SERVER['HTTP_X_APPYSHIFT_SIGNATURE'] ?? '';
if (!ctype_digit($timestamp) || abs(time() - (int) $timestamp) > 300) {
http_response_code(401);
exit('Stale webhook timestamp');
}
$expected = 'sha256=' . hash_hmac(
'sha256',
$timestamp . '.' . $rawBody,
$webhookSigningSecret
);
if (!hash_equals($expected, $received)) {
http_response_code(401);
exit('Invalid signature');
}
{
"id": 9821,
"event": "schedule.published",
"portal_slug": "acme",
"aggregate_type": "schedule_week",
"aggregate_id": "2026-08-17",
"payload": {
"week_start": "2026-08-17",
"week_end": "2026-08-23",
"shift_count": 42,
"notified_employee_count": 18,
"change_summary": {
"new_shifts": 4,
"removed_shifts": 1,
"time_changes": 2,
"changed_employees": 6,
"affected_employee_ids": [14, 22, 31, 42, 56, 61]
},
"publication_scope": {"date": null, "department_id": null},
"publication_scope_label": "the full week",
"remaining_draft_count": 0,
"published_by": 7,
"published_at": "2026-08-19T14:42:10-05:00"
},
"created_at": "2026-08-19 14:42:10"
}
{
"id": 9822,
"event": "pto.requested",
"portal_slug": "acme",
"aggregate_type": "time_off_request",
"aggregate_id": "417",
"payload": {
"request": {
"id": 417,
"employee_id": 42,
"employee_name": "Jordan Lee",
"type": "PTO",
"start_date": "2026-09-03",
"end_date": "2026-09-05",
"status": "PENDING"
},
"actor": {
"type": "EMPLOYEE",
"id": 42,
"name": "Jordan Lee"
},
"requested_at": "2026-08-19T14:48:22-05:00"
},
"created_at": "2026-08-19 14:48:22"
}
{
"id": 9825,
"event": "pto.approved",
"portal_slug": "acme",
"aggregate_type": "time_off_request",
"aggregate_id": "417",
"payload": {
"request": {
"id": 417,
"employee_id": 42,
"employee_name": "Jordan Lee",
"type": "PTO",
"start_date": "2026-09-03",
"end_date": "2026-09-05",
"days_requested": 3,
"previous_status": "PENDING",
"status": "APPROVED"
},
"approved_by": 7,
"approved_at": "2026-08-20T09:05:11-05:00"
},
"created_at": "2026-08-20 09:05:11"
}
{
"id": 9826,
"event": "pto.denied",
"portal_slug": "acme",
"aggregate_type": "time_off_request",
"aggregate_id": "418",
"payload": {
"request": {
"id": 418,
"employee_id": 56,
"employee_name": "Taylor Morgan",
"type": "UNPAID",
"start_date": "2026-09-08",
"end_date": "2026-09-08",
"days_requested": 1,
"previous_status": "PENDING",
"status": "DENIED"
},
"denied_by": 7,
"denied_at": "2026-08-20T09:08:14-05:00"
},
"created_at": "2026-08-20 09:08:14"
}
{
"id": 9827,
"event": "pto.cancelled",
"portal_slug": "acme",
"aggregate_type": "time_off_request",
"aggregate_id": "417",
"payload": {
"request": {
"id": 417,
"employee_id": 42,
"employee_name": "Jordan Lee",
"type": "PTO",
"start_date": "2026-09-03",
"end_date": "2026-09-05",
"days_requested": 3,
"previous_status": "APPROVED",
"status": "CANCELLED"
},
"cancelled_by": 7,
"cancelled_at": "2026-08-20T09:12:03-05:00"
},
"created_at": "2026-08-20 09:12:03"
}
{
"id": 9828,
"event": "time_entry.approved",
"portal_slug": "acme",
"aggregate_type": "time_entry",
"aggregate_id": "8031",
"payload": {
"time_entry": {
"id": 8031,
"employee_id": 42,
"employee_name": "Jordan Lee",
"shift_id": 5512,
"entry_date": "2026-08-19",
"clock_in": "2026-08-19 08:00:00",
"clock_out": "2026-08-19 16:30:00",
"break_minutes": 30,
"net_minutes": 480,
"status": "APPROVED",
"entry_source": "MOBILE"
},
"previous_status": "PENDING",
"approved_by": 7,
"approved_at": "2026-08-20T09:15:40-05:00"
},
"created_at": "2026-08-20 09:15:40"
}
{
"id": 9829,
"event": "time_entry.rejected",
"portal_slug": "acme",
"aggregate_type": "time_entry",
"aggregate_id": "8032",
"payload": {
"time_entry": {
"id": 8032,
"employee_id": 56,
"employee_name": "Taylor Morgan",
"shift_id": 5518,
"entry_date": "2026-08-19",
"clock_in": "2026-08-19 12:00:00",
"clock_out": "2026-08-19 20:15:00",
"break_minutes": 30,
"net_minutes": 465,
"status": "REJECTED",
"entry_source": "EMPLOYEE"
},
"previous_status": "PENDING",
"rejected_by": 7,
"rejected_at": "2026-08-20T09:17:22-05:00"
},
"created_at": "2026-08-20 09:17:22"
}
{
"id": 9830,
"event": "shift_swap.approved",
"portal_slug": "acme",
"aggregate_type": "shift_swap",
"aggregate_id": "284",
"payload": {
"swap": {
"id": 284,
"request_type": "GIVE_AWAY",
"requester_id": 42,
"requester_name": "Jordan Lee",
"requester_shift_id": 5512,
"requester_shift_date": "2026-08-22",
"requester_shift_time": "08:00:00-16:00:00",
"target_id": 56,
"target_name": "Taylor Morgan",
"target_shift_id": null,
"target_shift_date": null,
"target_shift_time": null,
"status": "APPROVED"
},
"previous_status": "TARGET_ACCEPTED",
"approved_by": null,
"approved_at": "2026-08-20T09:20:00-05:00"
},
"created_at": "2026-08-20 09:20:00"
}
{
"id": 9831,
"event": "shift_swap.rejected",
"portal_slug": "acme",
"aggregate_type": "shift_swap",
"aggregate_id": "285",
"payload": {
"swap": {
"id": 285,
"request_type": "SWAP",
"requester_id": 42,
"requester_name": "Jordan Lee",
"requester_shift_id": 5512,
"requester_shift_date": "2026-08-22",
"requester_shift_time": "08:00:00-16:00:00",
"target_id": 56,
"target_name": "Taylor Morgan",
"target_shift_id": 5520,
"target_shift_date": "2026-08-23",
"target_shift_time": "12:00:00-20:00:00",
"status": "REJECTED"
},
"previous_status": "TARGET_ACCEPTED",
"rejected_by": 7,
"rejected_at": "2026-08-20T09:22:05-05:00"
},
"created_at": "2026-08-20 09:22:05"
}
{
"id": 9830,
"event": "onboarding.completed",
"portal_slug": "acme",
"aggregate_type": "employee_onboarding",
"aggregate_id": "42",
"payload": {
"employee": {
"id": 42,
"display_name": "Jordan Lee",
"manager_id": 9,
"hire_date": "2026-08-24"
},
"completion": {
"completed_task_id": 812,
"available_task_count": 7,
"completed_task_count": 7,
"completed_at": "2026-08-20T11:15:00-05:00"
},
"actor": {"type": "EMPLOYEE", "id": 42}
},
"created_at": "2026-08-20 11:15:00"
}
{
"id": 9834,
"event": "payroll.exported",
"portal_slug": "acme",
"aggregate_type": "payroll_export",
"aggregate_id": "generic_payroll_20260810_20260823.csv",
"payload": {
"export": {
"provider": "generic",
"company_code": "ACME01",
"date_from": "2026-08-10",
"date_to": "2026-08-23",
"filename": "generic_payroll_20260810_20260823.csv",
"format": "csv",
"row_count": 18,
"total_hours": 1284.5,
"regular_hours": 1200,
"overtime_hours": 84.5,
"double_overtime_hours": 0,
"missing_payroll_id_count": 0
},
"exported_by": {"id": 7, "name": "Morgan Ellis"},
"exported_at": "2026-08-20T14:05:00-05:00"
},
"created_at": "2026-08-20 14:05:00"
}
{
"id": 9838,
"event": "tip_pool.approved",
"portal_slug": "acme",
"aggregate_type": "tip_pool",
"aggregate_id": "284",
"payload": {
"tip_pool": {
"id": 284,
"pool_date": "2026-08-19",
"work_location_id": 3,
"location": "Main Office",
"shift_label": "Dinner",
"total_tips": 842.35,
"split_method": "HOURS_WORKED",
"payroll_earning_code": "TIPS",
"source_type": "POLICY",
"allocation_count": 12,
"status": "APPROVED"
},
"approved_by": 7,
"approved_at": "2026-08-20T15:20:00-05:00"
},
"created_at": "2026-08-20 15:20:00"
}
Use these field-by-field contracts alongside the endpoint examples. Dynamic report and custom-field values inherit the sensitivity classification advertised by their field definition.
No schemas match that search.
Form fields accepted by the client-credentials token endpoint. Client authentication is sent separately with HTTP Basic authentication.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
grant_type |
string |
Required | No | Standard | Must be client_credentials. | client_credentials |
scope |
string |
Optional | No | Standard | Space-delimited subset of scopes granted to the client. Omit to request every granted scope. | employees:read reports:run |
Short-lived bearer credential returned after successful client authentication.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
access_token |
string |
Required | No | Credential | Bearer token. Store as a secret and never expose it to browser code. | aps_oauth_xxx |
token_type |
string |
Required | No | Standard | Authorization scheme used with the token. | Bearer |
expires_in |
integer |
Required | No | Standard | Token lifetime in seconds. | 3600 |
scope |
string |
Required | No | Standard | Space-delimited scopes carried by the token. | employees:read reports:run |
Identity and operation discovery for the bearer token used on the request.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data.api_version |
string |
Required | No | Standard | Protected API version described by the response. | v1 |
data.company_slug |
string |
Required | No | Standard | Company tenant bound to the token. | acme |
data.client.name |
string |
Required | No | Standard | Administrator-assigned integration name. | Payroll warehouse |
data.client.authentication |
enum |
Required | No | Standard | oauth2 or legacy_bearer. | oauth2 |
data.client.scopes |
array<string> |
Required | No | Standard | Exact scopes carried by this access token. | ["employees:read"] |
data.client.token_expires_at |
date-time |
Required | Yes | Standard | OAuth access-token expiry; null for a legacy bearer key. | 2026-08-20 16:30:00 |
data.client.client_expires_at |
date-time |
Required | Yes | Standard | Optional administrator-configured client expiry. | null |
data.operations |
array<ApiOperation> |
Required | No | Standard | Only operations whose required scopes are present on this token. | [{...}] |
data.operations[].method |
string |
Required | No | Standard | HTTP method. | GET |
data.operations[].path |
string |
Required | No | Standard | Versioned path appended to the company base URL. | /api/v1/employees |
data.operations[].required_scopes |
array<string> |
Required | No | Standard | Scopes required together for this operation. | ["employees:read"] |
meta.request_id |
string |
Required | No | Standard | Request correlation ID. | req_xxx |
meta.operation_count |
integer |
Required | No | Standard | Number of callable operations returned. | 3 |
Required inclusive date range shared by time-entry and schedule feeds.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
start_date |
date |
Required | No | Standard | First included date in YYYY-MM-DD format. | 2026-08-01 |
end_date |
date |
Required | No | Standard | Last included date; no more than 62 days after start_date. | 2026-08-14 |
Completed time entries within the requested date range.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data |
array<TimeEntry> |
Required | No | Conditional | Completed clock entries in chronological order. | [{...}] |
data[].id |
integer |
Required | No | Standard | Time-entry ID. | 8221 |
data[].employee_id |
integer |
Required | No | Standard | Employee ID. | 42 |
data[].employee_name |
string |
Required | No | Standard | Employee display name. | Jordan Lee |
data[].employee_payroll_id |
string |
Required | No | Conditional | External payroll identifier, or an empty string. | EE-1042 |
data[].work_date |
date |
Required | No | Standard | Work date assigned to the entry. | 2026-08-03 |
data[].clock_in |
date-time |
Required | No | Standard | Clock-in local database timestamp. | 2026-08-03 08:02:00 |
data[].clock_out |
date-time |
Required | No | Standard | Clock-out timestamp, advanced to the next day for overnight entries. | 2026-08-03 16:31:00 |
data[].hours |
number |
Required | No | Standard | Worked hours after breaks, rounded to four decimal places. | 8.0167 |
data[].entry_type |
string |
Required | No | Standard | Recorded entry source, defaulting to MANUAL on older schemas. | MOBILE |
data[].notes |
string |
Required | No | Conditional | Manager or employee notes, or an empty string. | "" |
meta.start_date |
date |
Required | No | Standard | Applied range start. | 2026-08-01 |
meta.end_date |
date |
Required | No | Standard | Applied range end. | 2026-08-14 |
meta.row_count |
integer |
Required | No | Standard | Entries returned. | 1 |
Scheduled shift assignments within the requested date range.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data |
array<ScheduleShift> |
Required | No | Standard | Shifts ordered by date and start time. | [{...}] |
data[].id |
integer |
Required | No | Standard | Shift ID. | 5512 |
data[].employee_id |
integer |
Required | No | Standard | Assigned employee ID. | 42 |
data[].employee_name |
string |
Required | No | Standard | Assigned employee name. | Jordan Lee |
data[].employee_payroll_id |
string |
Required | No | Conditional | External payroll identifier, or an empty string. | EE-1042 |
data[].shift_date |
date |
Required | No | Standard | Scheduled work date. | 2026-08-18 |
data[].start_time |
time |
Required | No | Standard | Local shift start time. | 08:00:00 |
data[].end_time |
time |
Required | No | Standard | Local shift end time. | 16:00:00 |
data[].status |
string |
Required | No | Standard | Shift publication or workflow status. | PUBLISHED |
data[].location |
string |
Required | No | Standard | Shift location label, or an empty string. | Main Office |
data[].notes |
string |
Required | No | Conditional | Shift notes, or an empty string. | "" |
data[].position_title |
string |
Required | No | Standard | Shift position title, or an empty string. | Guest Services Lead |
data[].department_name |
string |
Required | No | Standard | Assigned employee department, or an empty string. | Front Desk |
meta.row_count |
integer |
Required | No | Standard | Shifts returned. | 1 |
Selects either request history or annual leave balances.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
view |
enum |
Optional | No | Standard | requests (default) or balances. | requests |
start_date |
date |
Optional | No | Standard | Request-overlap range start; defaults to 90 days ago. | 2026-08-01 |
end_date |
date |
Optional | No | Standard | Request-overlap range end; defaults to today. | 2026-09-30 |
employee_id |
integer |
Optional | No | Standard | Optional employee filter for the requests view. | 42 |
year |
integer |
Optional | No | Standard | Four-digit year for the balances view; defaults to the current year. | 2026 |
Time-off request rows or leave-balance rows selected by the view query.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data |
array<TimeOffRequest|LeaveBalance> |
Required | No | Conditional | Rows for the selected view. | [{...}] |
data[].employee_id |
integer |
Required | No | Standard | Employee ID. | 42 |
data[].employee_name |
string |
Required | No | Standard | Employee name. | Jordan Lee |
data[].employee_payroll_id |
string |
Required | No | Conditional | External payroll identifier, or an empty string. | EE-1042 |
data[].id |
integer |
Optional | No | Standard | Request ID; requests view only. | 381 |
data[].type |
string |
Optional | No | Standard | Request leave type; requests view only. | VACATION |
data[].start_date |
date |
Optional | No | Standard | Request start; requests view only. | 2026-09-08 |
data[].end_date |
date |
Optional | No | Standard | Request end; requests view only. | 2026-09-10 |
data[].status |
string |
Optional | No | Standard | Request workflow status. | APPROVED |
data[].reason |
string |
Optional | No | Conditional | Employee-provided reason. | Family trip |
data[].year |
integer |
Optional | No | Standard | Balance year; balances view only. | 2026 |
data[].leave_type |
string |
Optional | No | Standard | Balance leave type. | VACATION |
data[].allotted_hours |
number |
Optional | No | Conditional | Hours allotted for the year. | 80 |
data[].used_hours |
number |
Optional | No | Conditional | Hours used for the year. | 24 |
data[].remaining_hours |
number |
Optional | No | Conditional | Allotted minus used hours. | 56 |
meta.view |
enum |
Required | No | Standard | requests or balances. | requests |
meta.row_count |
integer |
Required | No | Standard | Rows returned. | 1 |
Optional filters for employee certifications and licenses.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
employee_id |
integer |
Optional | No | Standard | Return credentials for one employee. | 42 |
status |
string |
Optional | No | Standard | Exact credential status, normalized to uppercase. | ACTIVE |
expiring_within_days |
integer |
Optional | No | Standard | Return unexpired credentials expiring within this many days. | 60 |
Employee certification and license records.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data |
array<Credential> |
Required | No | Conditional | Matching credentials. | [{...}] |
data[].id |
integer |
Required | No | Standard | Credential record ID. | 91 |
data[].employee_id |
integer |
Required | No | Standard | Employee ID. | 42 |
data[].certification_name |
string |
Required | No | Standard | Certification or license name. | Food Handler |
data[].credential_number |
string |
Required | No | Conditional | Credential number, or an empty string. | FH-10293 |
data[].issued_at |
date |
Required | Yes | Standard | Issue date. | 2026-01-10 |
data[].expires_at |
date |
Required | Yes | Standard | Expiry date. | 2027-01-10 |
data[].status |
string |
Required | No | Standard | Credential workflow status. | ACTIVE |
data[].verified_at |
date-time |
Required | Yes | Standard | Verification timestamp. | 2026-01-11 10:00:00 |
meta.row_count |
integer |
Required | No | Standard | Credentials returned. | 1 |
Company departments and current active employee counts.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data[].id |
integer |
Required | No | Standard | Department ID. | 7 |
data[].name |
string |
Required | No | Standard | Department name. | Front Desk |
data[].description |
string |
Required | No | Standard | Description, or an empty string. | Guest arrival team |
data[].color |
string |
Required | No | Standard | Configured display color. | #2563eb |
data[].employee_count |
integer |
Required | No | Standard | Active employees in the department. | 12 |
Company job positions and current active employee counts.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data[].id |
integer |
Required | No | Standard | Position ID. | 12 |
data[].title |
string |
Required | No | Standard | Position title. | Guest Services Lead |
data[].description |
string |
Required | No | Standard | Description, or an empty string. | Leads guest arrival operations |
data[].department_name |
string |
Required | No | Standard | Related department, or an empty string. | Front Desk |
data[].employee_count |
integer |
Required | No | Standard | Active employees in the position. | 3 |
Company work locations, addresses, and time-clock geofence settings.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data[].id |
integer |
Required | No | Standard | Location ID. | 3 |
data[].name |
string |
Required | No | Standard | Location name. | Main Office |
data[].address |
string |
Required | No | Conditional | Street address, or an empty string. | 100 Main St |
data[].city |
string |
Required | No | Conditional | City, or an empty string. | Austin |
data[].state |
string |
Required | No | Conditional | State or region, or an empty string. | TX |
data[].zip |
string |
Required | No | Conditional | Postal code, or an empty string. | 78701 |
data[].lat |
number |
Required | Yes | Conditional | Latitude. | 30.2672 |
data[].lon |
number |
Required | Yes | Conditional | Longitude. | -97.7431 |
data[].is_active |
boolean |
Required | No | Standard | Whether the work location is active. | true |
data[].geofence_radius_feet |
integer |
Required | Yes | Conditional | Allowed clock radius in feet. | 500 |
data[].employee_count |
integer |
Required | No | Standard | Active employees assigned to the location. | 18 |
Optional filter used by employee-associated collection feeds.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
employee_id |
integer |
Optional | No | Standard | Return rows for one employee. | 42 |
Active employee deduction elections and employer matching amounts.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data[].employee_id |
integer |
Required | No | Standard | Employee ID. | 42 |
data[].employee_name |
string |
Required | No | Standard | Employee name. | Jordan Lee |
data[].employee_payroll_id |
string |
Required | No | Conditional | External payroll identifier, or an empty string. | EE-1042 |
data[].code |
string |
Required | No | Standard | Deduction code. | MEDICAL |
data[].label |
string |
Required | No | Standard | Deduction label. | Medical Plan |
data[].deduction_type |
string |
Required | No | Standard | Configured deduction type. | PRE_TAX |
data[].employee_amount |
number |
Required | No | Sensitive | Employee deduction amount. | 85.25 |
data[].employer_match |
number |
Required | No | Sensitive | Employer matching amount. | 50 |
JSON body assigning or clearing one employee’s external payroll identifier.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
payroll_id |
string |
Required | No | Conditional | External payroll identifier up to 80 characters. Send an empty string to clear it. | EE-1042 |
Employee identity summary after a payroll-ID update.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data.id |
integer |
Required | No | Standard | Employee ID. | 42 |
data.name |
string |
Required | No | Standard | Employee name. | Jordan Lee |
data.email |
string |
Required | No | Standard | Employee email. | jordan.lee@example.com |
data.payroll_id |
string |
Required | No | Conditional | Stored payroll identifier, or an empty string after clearing. | EE-1042 |
data.active |
boolean |
Required | No | Standard | Whether employee status is ACTIVE. | true |
meta.request_id |
string |
Required | No | Standard | Request correlation ID. | req_xxx |
Optional query parameters for filtering and cursor-paginating the employee roster.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
status |
enum |
Optional | No | Standard | ACTIVE, INACTIVE, ON_LEAVE, or TERMINATED. | ACTIVE |
department_id |
integer |
Optional | No | Standard | Positive department ID. | 7 |
updated_since |
date-time |
Optional | No | Standard | ISO 8601 date or timestamp, inclusive. | 2026-08-01T00:00:00Z |
limit |
integer |
Optional | No | Standard | Enables cursor pagination. Range 1-500; defaults to 100 when pagination is requested. | 100 |
after_id |
integer |
Optional | No | Standard | Return employees with IDs greater than this cursor. | 42 |
A standard employee roster page. Sensitive profile and custom values are intentionally excluded.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data |
array<EmployeeSummary> |
Required | No | Standard | Employees visible within the company tenant. | [{...}] |
data[].id |
integer |
Required | No | Standard | Employee ID used by detail and field-value endpoints. | 42 |
data[].name |
string |
Required | No | Standard | Legal first and last name joined for display. | Jordan Lee |
data[].email |
string |
Required | No | Standard | Work email stored on the employee profile. | jordan.lee@example.com |
data[].payroll_id |
string |
Required | No | Standard | External payroll identifier; an empty string means none is assigned. | EE-1042 |
data[].department_id |
integer |
Required | Yes | Standard | Department relationship ID. | 7 |
data[].department |
string |
Required | No | Standard | Department display name, or an empty string. | Front Desk |
data[].position_id |
integer |
Required | Yes | Standard | Position relationship ID. | 12 |
data[].job_title |
string |
Required | No | Standard | Position title, or an empty string. | Guest Services Lead |
data[].pay_type |
string |
Required | No | Standard | Employee pay type without compensation values. | HOURLY |
data[].status |
enum |
Required | No | Standard | Current employee status. | ACTIVE |
data[].active |
boolean |
Required | No | Standard | True only when status is ACTIVE. | true |
data[].updated_at |
date-time |
Required | No | Standard | Application database timestamp. | 2026-08-18 14:22:09 |
meta.request_id |
string |
Required | No | Standard | Request correlation ID used in access logs. | req_xxx |
meta.row_count |
integer |
Required | No | Standard | Employees returned in this response. | 1 |
meta.pagination.applied |
boolean |
Required | No | Standard | Whether limit or after_id enabled cursor pagination. | true |
meta.pagination.limit |
integer |
Required | Yes | Standard | Applied page size, or null for the backward-compatible unpaginated response. | 100 |
meta.pagination.has_more |
boolean |
Required | No | Standard | Whether another cursor page exists. | false |
meta.pagination.next_after_id |
integer |
Required | Yes | Standard | Pass this value as after_id for the next page. | 42 |
One employee’s standard non-sensitive profile and organization relationships.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data.id |
integer |
Required | No | Standard | Employee ID. | 42 |
data.first_name |
string |
Required | No | Standard | Legal first name. | Jordan |
data.last_name |
string |
Required | No | Standard | Legal last name. | Lee |
data.preferred_name |
string |
Required | No | Standard | Preferred name, or an empty string. | Jordy |
data.name |
string |
Required | No | Standard | Legal first and last name joined for display. | Jordan Lee |
data.email |
string |
Required | No | Standard | Work email. | jordan.lee@example.com |
data.phone |
string |
Required | No | Standard | Primary phone, or an empty string. | 555-123-4567 |
data.status |
enum |
Required | No | Standard | Current employee status. | ACTIVE |
data.employment_type |
string |
Required | No | Standard | Employment classification. | FULL_TIME |
data.department_id |
integer |
Required | Yes | Standard | Department relationship ID. | 7 |
data.department |
string |
Required | No | Standard | Department display name. | Front Desk |
data.position_id |
integer |
Required | Yes | Standard | Position relationship ID. | 12 |
data.position |
string |
Required | No | Standard | Position title. | Guest Services Lead |
data.manager_id |
integer |
Required | Yes | Standard | Manager employee ID. | 9 |
data.manager |
string |
Required | No | Standard | Manager display name, or an empty string. | Morgan Ellis |
data.hire_date |
date |
Required | No | Standard | ISO date, or an empty string. | 2026-05-01 |
data.termination_date |
date |
Required | No | Standard | ISO date, or an empty string. | "" |
data.location |
string |
Required | No | Standard | Legacy work-location label, or an empty string. | Main Office |
data.payroll_id |
string |
Required | No | Standard | External payroll identifier, or an empty string. | EE-1042 |
data.portal_enabled |
boolean |
Required | No | Standard | Whether employee self-service access is enabled. | true |
data.created_at |
date-time |
Required | No | Standard | Profile creation timestamp. | 2026-04-20 09:13:00 |
data.updated_at |
date-time |
Required | No | Standard | Last profile update timestamp. | 2026-08-18 14:22:09 |
meta.request_id |
string |
Required | No | Standard | Request correlation ID. | req_xxx |
Query parameters for selecting reportable fields and their display formats for one employee.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
fields |
string |
Optional | No | Standard | Comma-separated field keys. Omit to return every field available to the token; maximum 500. | employee_name,hire_date,custom_17 |
formats[field_key] |
string |
Optional | No | Standard | Requested format key for a selected field. The response uses the catalog’s advertised output_field. | formats[hire_date]=us |
include_sensitive |
boolean |
Optional | No | Sensitive | Set to 1 only with reports.sensitive:read to expose sensitive fields. | 0 |
Formatted reportable values for one employee. Keys inside values depend on selected fields and formats.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data.employee_id |
integer |
Required | No | Standard | Employee ID. | 42 |
data.values |
object<string, scalar|null> |
Required | No | Conditional | Dynamic map keyed by each selected format’s output_field. Classification inherits from its field definition. | {"hire_date_us":"05/01/2026"} |
meta.request_id |
string |
Required | No | Standard | Request correlation ID. | req_xxx |
meta.field_count |
integer |
Required | No | Standard | Number of output values returned. | 3 |
meta.fields |
array<FieldSelection> |
Required | No | Standard | Mapping from requested field keys to output keys. | [{...}] |
meta.fields[].field |
string |
Required | No | Standard | Requested catalog field key. | hire_date |
meta.fields[].output_field |
string |
Required | No | Standard | Key used in data.values after formatting. | hire_date_us |
meta.fields[].label |
string |
Required | No | Standard | Human-readable field label. | Hire Date |
meta.fields[].format |
string |
Required | No | Standard | Applied format key. | us |
meta.fields[].sensitive |
boolean |
Required | No | Standard | Whether the corresponding value is sensitive HR data. | false |
meta.sensitive_fields_included |
boolean |
Required | No | Standard | Whether include_sensitive was authorized and applied. | false |
Partial update body for active, reportable custom employee fields. Omitted fields remain unchanged.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
values |
object<string, scalar|null> |
Required | No | Conditional | Non-empty map containing at most 100 custom_N keys. Classification inherits from each field definition. | {"custom_17":"Extra Large"} |
values.custom_N |
string|number|boolean|null |
Required | Yes | Conditional | Value validated against the custom field type, required flag, and configured options. | Extra Large |
Normalized values returned after a successful partial custom-field update.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data.employee_id |
integer |
Required | No | Standard | Employee ID. | 42 |
data.values |
object<string, string> |
Required | No | Conditional | Only submitted custom_N fields, normalized to stored strings. | {"custom_31":"1"} |
meta.request_id |
string |
Required | No | Standard | Request correlation ID. | req_xxx |
meta.changed_fields |
array<string> |
Required | No | Standard | Submitted keys whose stored value actually changed. | ["custom_17"] |
Optional query parameter controlling whether sensitive field definitions are visible.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
include_sensitive |
boolean |
Optional | No | Sensitive | Set to 1 only with reports.sensitive:read. | 0 |
Field definitions used to build selectors, validate custom-field writes, and request consistent output formats.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data |
array<EmployeeFieldDefinition> |
Required | No | Standard | Reportable fields visible to this token. | [{...}] |
data[].key |
string |
Required | No | Standard | Stable request key such as employee_name or custom_17. | employee_name |
data[].label |
string |
Required | No | Standard | Human-readable label. | Employee |
data[].group |
string |
Required | No | Standard | UI grouping label. | Identity |
data[].source |
enum |
Required | No | Standard | system or custom. | system |
data[].type |
string |
Required | No | Standard | system for built-ins; configured field type for custom fields. | system |
data[].custom_field_id |
integer |
Required | Yes | Standard | Numeric ID for custom fields; null for system fields. | 17 |
data[].writable |
boolean |
Required | No | Standard | Whether the field may be updated by the custom-field PATCH endpoint. | true |
data[].required |
boolean |
Required | No | Standard | Whether a custom field rejects an empty value. | false |
data[].options |
array<string> |
Required | No | Standard | Configured values for choice fields; otherwise empty. | ["Small","Large"] |
data[].available_on_roster |
boolean |
Required | No | Standard | Whether the field can appear as an employee roster column. | true |
data[].sensitive |
boolean |
Required | No | Standard | Whether values require sensitive-data authority. | false |
data[].formats |
array<FieldFormat> |
Required | No | Standard | Supported display formats; may be empty. | [{...}] |
data[].formats[].key |
string |
Required | No | Standard | Format key sent in formats[field_key]. | last_first |
data[].formats[].label |
string |
Required | No | Standard | Format display label. | Last, First |
data[].formats[].output_field |
string |
Required | No | Standard | Response property produced by this format. | employee_last_first |
meta.request_id |
string |
Required | No | Standard | Request correlation ID. | req_xxx |
meta.row_count |
integer |
Required | No | Standard | Field definitions returned. | 48 |
meta.sensitive_fields_included |
boolean |
Required | No | Standard | Whether sensitive definitions were authorized and included. | false |
Optional query parameter controlling sensitive saved definitions, datasets, and columns.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
include_sensitive |
boolean |
Optional | No | Sensitive | Set to 1 only with reports.sensitive:read. | 0 |
Saved report definitions plus the datasets and columns currently available to the token.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data |
array<SavedReport> |
Required | No | Conditional | Saved report definitions filtered to authorized columns. | [{...}] |
data[].id |
integer |
Required | No | Standard | Saved report ID accepted by ReportRunRequest.report_id. | 18 |
data[].name |
string |
Required | No | Standard | Saved report name. | Active employee roster |
data[].description |
string |
Required | No | Standard | Saved report description. | Current employees for payroll review |
data[].dataset |
string |
Required | No | Standard | Dataset key. | employee_roster |
data[].columns |
array<string> |
Required | No | Conditional | Authorized base column keys selected by the saved report. | ["employee_name","department"] |
data[].column_formats |
object<string, string> |
Required | No | Standard | Format key by base column. | {"employee_name":"last_first"} |
data[].filters |
object |
Required | No | Conditional | Stored dataset filters after authorization filtering. | {"status":"ACTIVE"} |
data[].updated_at |
date-time |
Required | No | Standard | Last saved-definition update timestamp. | 2026-08-18 11:45:00 |
datasets |
object<string, DatasetDefinition> |
Required | No | Conditional | Dataset definitions keyed by dataset name. | {"employee_roster":{...}} |
datasets.{dataset}.label |
string |
Required | No | Standard | Dataset display label. | Employee roster |
datasets.{dataset}.date_enabled |
boolean |
Required | No | Standard | Whether the dataset accepts date-range filters. | false |
datasets.{dataset}.default_columns |
array<string> |
Required | No | Conditional | Default authorized column keys. | ["employee_name","department"] |
datasets.{dataset}.columns |
object<string, object> |
Required | No | Conditional | Authorized column definitions keyed by field name. | {"employee_name":{...}} |
meta.request_id |
string |
Required | No | Standard | Request correlation ID. | req_xxx |
meta.row_count |
integer |
Required | No | Standard | Saved reports returned. | 1 |
meta.sensitive_fields_included |
boolean |
Required | No | Standard | Whether sensitive definitions were authorized and included. | false |
JSON body for a saved or ad-hoc report. Ad-hoc selections override the corresponding saved-report values.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
report_id |
integer |
Optional | No | Standard | Saved report ID. Optional when dataset and columns are supplied directly. | 18 |
dataset |
string |
Optional | No | Standard | Dataset key. Defaults to the saved report or employee_roster. | employee_roster |
columns |
array<string> |
Optional | No | Conditional | Authorized base column keys to return. | ["employee_name","department"] |
column_formats |
object<string, string> |
Optional | No | Standard | Format key by selected base column. | {"employee_name":"last_first"} |
column_labels |
object<string, string> |
Optional | No | Standard | Optional output labels keyed by base column. | {"employee_name":"Team member"} |
filters |
object |
Optional | No | Conditional | Dataset-specific filters. Values are validated and filtered by the reporting service. | {"status":"ACTIVE"} |
metadata |
object<string, scalar|null> |
Optional | No | Conditional | Opaque client correlation data echoed as meta.client_metadata. Use up to 50 flat entries; keys are limited to 64 characters, string values to 1,000 bytes, and the object to 16 KB. | {"workflow_run_id":"sync_2026_08_19_001"} |
include_sensitive |
boolean |
Optional | No | Sensitive | Set to true only with reports.sensitive:read. | false |
Projected report rows and metadata describing the exact output columns.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
data |
array<object> |
Required | No | Conditional | Rows keyed by selected output field. Shape and sensitivity depend on the request. | [{"department":"Front Desk"}] |
data[].{output_field} |
scalar|null |
Required | Yes | Conditional | Formatted report cell. Classification inherits from its selected column. | Front Desk |
meta.request_id |
string |
Required | No | Standard | Request correlation ID. | req_xxx |
meta.report_id |
integer |
Required | Yes | Standard | Saved report ID, or null for an ad-hoc run. | 18 |
meta.dataset |
string |
Required | No | Standard | Dataset that produced the result. | employee_roster |
meta.row_count |
integer |
Required | No | Standard | Rows returned. | 1 |
meta.columns |
array<OutputColumn> |
Required | No | Conditional | Ordered output keys and labels. | [{...}] |
meta.columns[].key |
string |
Required | No | Conditional | Property name used in each data row. | employee_last_first |
meta.columns[].label |
string |
Required | No | Standard | Resolved column label. | Employee |
meta.sensitive_fields_included |
boolean |
Required | No | Standard | Whether sensitive fields were authorized and included. | false |
meta.client_metadata |
object<string, scalar|null> |
Required | No | Conditional | Validated request metadata echoed unchanged, or an empty object when omitted. AppyShift does not interpret or persist these values. | {"workflow_run_id":"sync_2026_08_19_001"} |
JSON object delivered for every webhook event. The payload shape is selected by event, while the envelope remains stable.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
id |
integer |
Required | No | Standard | Tenant event-outbox ID. Use the delivery header, not this ID, to deduplicate individual delivery attempts. | 9821 |
event |
string |
Required | No | Standard | Event name used by webhook filters and the X-AppyShift-Event header. | schedule.published |
portal_slug |
string |
Required | No | Standard | Company tenant that produced the event. | acme |
aggregate_type |
string |
Required | Yes | Standard | Resource family associated with the event, when available. | schedule_week |
aggregate_id |
string |
Required | Yes | Standard | String form of the associated resource identifier, when available. | 2026-08-17 |
payload |
object |
Required | No | Conditional | Event-specific payload. See the payload schema linked from the event catalog. | {...} |
created_at |
date-time |
Required | No | Standard | Database timestamp recorded when AppyShift accepted the event. | 2026-08-19 14:42:10 |
Payload for employee.created and employee.updated. It includes operational profile data and selected compensation/contact fields, but excludes SSN, birth date, home address, notes, documents, and profile-photo filenames.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
employee |
object |
Required | No | Conditional | Employee state after the committed change. | {...} |
employee.id |
integer |
Required | No | Standard | Employee ID. | 42 |
employee.display_name |
string |
Required | No | Standard | Resolved display name. | Jordan Lee |
employee.first_name |
string |
Required | No | Standard | Legal first name. | Jordan |
employee.last_name |
string |
Required | No | Standard | Legal last name. | Lee |
employee.preferred_name |
string |
Required | Yes | Standard | Preferred name when one is stored. | Jordy |
employee.email |
string |
Required | No | Standard | Employee email address. | jordan.lee@example.com |
employee.phone |
string |
Required | Yes | Sensitive | Primary phone value. | 555-123-4567 |
employee.cell_phone |
string |
Required | Yes | Sensitive | Personal mobile phone value. | 555-123-4567 |
employee.home_phone |
string |
Required | Yes | Sensitive | Home phone value. | 555-987-6543 |
employee.status |
enum |
Required | No | Standard | Current employment status. | ACTIVE |
employee.employment_type |
string |
Required | Yes | Standard | Employment classification. | FULL_TIME |
employee.department_id |
integer |
Required | Yes | Standard | Department relationship ID. | 7 |
employee.department_name |
string |
Required | Yes | Standard | Department name. | Front Desk |
employee.position_id |
integer |
Required | Yes | Standard | Position relationship ID. | 12 |
employee.position_title |
string |
Required | Yes | Standard | Position title. | Guest Services Lead |
employee.manager_id |
integer |
Required | Yes | Standard | Manager employee ID. | 9 |
employee.manager_name |
string |
Required | Yes | Standard | Manager display name. | Morgan Ellis |
employee.hire_date |
date |
Required | No | Standard | Original hire date. | 2026-05-01 |
employee.rehire_date |
date |
Required | Yes | Standard | Most recent rehire date. | 2026-05-01 |
employee.termination_date |
date |
Required | Yes | Standard | Termination date when applicable. | 2026-12-31 |
employee.termination_reason |
string |
Required | Yes | Sensitive | Stored termination reason. | Voluntary |
employee.is_rehirable |
boolean |
Required | Yes | Sensitive | Rehire eligibility when recorded. | true |
employee.location |
string |
Required | Yes | Standard | Legacy work-location label. | Main Office |
employee.work_location_id |
integer |
Required | Yes | Standard | Work-location relationship ID. | 3 |
employee.pay_type |
string |
Required | Yes | Standard | Hourly or salary pay classification. | HOURLY |
employee.pay_rate |
number |
Required | Yes | Sensitive | Stored pay rate. Webhook administration should be restricted to trusted company administrators. | 24.50 |
employee.payroll_id |
string |
Required | Yes | Sensitive | External payroll identifier. | EE-1042 |
employee.time_clock_badge_id |
string |
Required | Yes | Sensitive | External clock/badge identifier. | 1042 |
employee.pto_policy_id |
integer |
Required | Yes | Standard | Assigned time-off policy ID. | 5 |
employee.portal_enabled |
boolean |
Required | No | Standard | Whether employee self-service access is enabled. | true |
employee.created_at |
date-time |
Required | No | Standard | Profile creation timestamp. | 2026-04-20 09:13:00 |
employee.updated_at |
date-time |
Required | No | Standard | Latest profile update timestamp. | 2026-08-19 14:42:10 |
previous_employee |
object |
Optional | No | Conditional | Previous employee state on employee.updated. Omitted on employee.created. | {...} |
changed_fields |
array<string> |
Required | No | Conditional | Properties that changed. Empty for employee.created. | ["department_id","department_name"] |
context |
object |
Required | No | Standard | Lifecycle source, timestamp, and operation-specific context. | {"source":"employees","occurred_at":"2026-08-19T14:42:10-05:00"} |
actor |
object |
Optional | No | Standard | Authenticated user that caused the change, when available. | {"id":7,"name":"Morgan Ellis","email":"morgan@example.com"} |
Payload produced when a full or scoped weekly schedule publication changes the employee-visible schedule.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
week_start |
date |
Required | No | Standard | First date in the published week. | 2026-08-17 |
week_end |
date |
Required | No | Standard | Last date in the published week. | 2026-08-23 |
shift_count |
integer |
Required | No | Standard | Published shifts in the selected scope. | 42 |
notified_employee_count |
integer |
Required | No | Standard | Employees selected for schedule-change notification. | 18 |
change_summary |
object |
Required | No | Standard | Counts and employee IDs describing the published difference. | {"new_shifts":4,"removed_shifts":1,"time_changes":2,"changed_employees":6,"affected_employee_ids":[14,22,31]} |
publication_scope |
object |
Required | No | Standard | Optional date and department filters used for scoped publication. | {"date":null,"department_id":null} |
publication_scope_label |
string |
Required | No | Standard | Human-readable publication scope. | the full week |
remaining_draft_count |
integer |
Required | No | Standard | Draft changes still outside the selected scope. | 0 |
published_by |
integer |
Required | Yes | Standard | User ID that published the schedule. | 7 |
published_at |
date-time |
Required | No | Standard | ISO 8601 publication timestamp. | 2026-08-19T14:42:10-05:00 |
Payload produced when an employee, manager, or administrator submits a time-off request. The pto.requested event name is retained for compatibility and applies to every leave type.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
request.id |
integer |
Required | No | Standard | Time-off request ID. | 417 |
request.employee_id |
integer |
Required | No | Standard | Requesting employee ID. | 42 |
request.employee_name |
string |
Required | Yes | Standard | Requesting employee display name when available. | Jordan Lee |
request.type |
string |
Required | No | Standard | Requested leave type. | PTO |
request.start_date |
date |
Required | No | Standard | First requested date. | 2026-09-03 |
request.end_date |
date |
Required | No | Standard | Last requested date. | 2026-09-05 |
request.status |
enum |
Required | No | Standard | Initial request status. | PENDING |
actor |
object |
Required | Yes | Standard | Employee or authenticated user that submitted the request. | {"type":"EMPLOYEE","id":42,"name":"Jordan Lee"} |
requested_at |
date-time |
Required | No | Standard | ISO 8601 submission timestamp. | 2026-08-19T14:48:22-05:00 |
Payload produced when a time-off request moves to approved. Free-text reasons and reviewer notes are intentionally excluded.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
request.id |
integer |
Required | No | Standard | Time-off request ID. | 417 |
request.employee_id |
integer |
Required | No | Standard | Approved employee ID. | 42 |
request.employee_name |
string |
Required | Yes | Standard | Approved employee display name when available. | Jordan Lee |
request.type |
string |
Required | No | Standard | Approved leave type. | PTO |
request.start_date |
date |
Required | No | Standard | First approved date. | 2026-09-03 |
request.end_date |
date |
Required | No | Standard | Last approved date. | 2026-09-05 |
request.days_requested |
integer |
Required | No | Standard | Inclusive calendar-day count. | 3 |
request.previous_status |
enum |
Required | No | Standard | Status before approval. | PENDING |
request.status |
enum |
Required | No | Standard | New request status. | APPROVED |
approved_by |
integer |
Required | Yes | Standard | Reviewing user ID. | 7 |
approved_at |
date-time |
Required | No | Standard | ISO 8601 approval timestamp. | 2026-08-20T09:05:11-05:00 |
Payload produced when a time-off request moves to denied. Free-text reasons and reviewer notes are intentionally excluded.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
request.id |
integer |
Required | No | Standard | Time-off request ID. | 418 |
request.employee_id |
integer |
Required | No | Standard | Requesting employee ID. | 56 |
request.employee_name |
string |
Required | Yes | Standard | Employee display name when available. | Taylor Morgan |
request.type |
string |
Required | No | Standard | Requested leave type. | UNPAID |
request.start_date |
date |
Required | No | Standard | First requested date. | 2026-09-08 |
request.end_date |
date |
Required | No | Standard | Last requested date. | 2026-09-08 |
request.days_requested |
integer |
Required | No | Standard | Inclusive calendar-day count. | 1 |
request.previous_status |
enum |
Required | No | Standard | Status before denial. | PENDING |
request.status |
enum |
Required | No | Standard | New request status. | DENIED |
denied_by |
integer |
Required | Yes | Standard | Reviewing user ID. | 7 |
denied_at |
date-time |
Required | No | Standard | ISO 8601 denial timestamp. | 2026-08-20T09:08:14-05:00 |
Payload produced when a manager or administrator moves a time-off request to cancelled. Free-text reasons and reviewer notes are intentionally excluded.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
request.id |
integer |
Required | No | Standard | Time-off request ID. | 417 |
request.employee_id |
integer |
Required | No | Standard | Requesting employee ID. | 42 |
request.employee_name |
string |
Required | Yes | Standard | Employee display name when available. | Jordan Lee |
request.type |
string |
Required | No | Standard | Requested leave type. | PTO |
request.start_date |
date |
Required | No | Standard | First requested date. | 2026-09-03 |
request.end_date |
date |
Required | No | Standard | Last requested date. | 2026-09-05 |
request.days_requested |
integer |
Required | No | Standard | Inclusive calendar-day count. | 3 |
request.previous_status |
enum |
Required | No | Standard | Status before cancellation. | APPROVED |
request.status |
enum |
Required | No | Standard | New request status. | CANCELLED |
cancelled_by |
integer |
Required | Yes | Standard | User ID that cancelled the request. | 7 |
cancelled_at |
date-time |
Required | No | Standard | ISO 8601 cancellation timestamp. | 2026-08-20T09:12:03-05:00 |
Payload produced after a reviewed time entry is approved.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
time_entry.id |
integer |
Required | No | Standard | Time-entry ID. | 8031 |
time_entry.employee_id |
integer |
Required | No | Standard | Employee ID. | 42 |
time_entry.employee_name |
string |
Required | No | Standard | Employee display name. | Jordan Lee |
time_entry.shift_id |
integer |
Required | Yes | Standard | Associated scheduled-shift ID. | 5512 |
time_entry.entry_date |
date |
Required | No | Standard | Work date. | 2026-08-19 |
time_entry.clock_in |
date-time |
Required | No | Standard | Recorded clock-in value. | 2026-08-19 08:00:00 |
time_entry.clock_out |
date-time |
Required | No | Standard | Recorded clock-out value. | 2026-08-19 16:30:00 |
time_entry.break_minutes |
integer |
Required | No | Standard | Unpaid break minutes. | 30 |
time_entry.net_minutes |
integer |
Required | No | Standard | Net approved work minutes. | 480 |
time_entry.status |
enum |
Required | No | Standard | New entry status. | APPROVED |
time_entry.entry_source |
string |
Required | No | Standard | Origin of the time entry. | MOBILE |
previous_status |
enum |
Required | No | Standard | Status before approval. | PENDING |
approved_by |
integer |
Required | No | Standard | Reviewing user ID. | 7 |
approved_at |
date-time |
Required | No | Standard | ISO 8601 approval timestamp. | 2026-08-20T09:05:11-05:00 |
Payload produced after a reviewed time entry is rejected. Free-text review notes are intentionally excluded.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
time_entry.id |
integer |
Required | No | Standard | Time-entry ID. | 8032 |
time_entry.employee_id |
integer |
Required | No | Standard | Employee ID. | 56 |
time_entry.employee_name |
string |
Required | No | Standard | Employee display name. | Taylor Morgan |
time_entry.shift_id |
integer |
Required | Yes | Standard | Associated scheduled-shift ID. | 5518 |
time_entry.entry_date |
date |
Required | No | Standard | Work date. | 2026-08-19 |
time_entry.clock_in |
date-time |
Required | No | Standard | Recorded clock-in value. | 2026-08-19 12:00:00 |
time_entry.clock_out |
date-time |
Required | No | Standard | Recorded clock-out value. | 2026-08-19 20:15:00 |
time_entry.break_minutes |
integer |
Required | No | Standard | Unpaid break minutes. | 30 |
time_entry.net_minutes |
integer |
Required | No | Standard | Net recorded work minutes. | 465 |
time_entry.status |
enum |
Required | No | Standard | New entry status. | REJECTED |
time_entry.entry_source |
string |
Required | No | Standard | Origin of the time entry. | EMPLOYEE |
previous_status |
enum |
Required | No | Standard | Status before rejection. | PENDING |
rejected_by |
integer |
Required | Yes | Standard | Reviewing user ID. | 7 |
rejected_at |
date-time |
Required | No | Standard | ISO 8601 rejection timestamp. | 2026-08-20T09:17:22-05:00 |
Payload produced after a shift swap or shift-board pickup is approved.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
swap.id |
integer |
Required | No | Standard | Coverage-request ID. | 284 |
swap.request_type |
enum |
Required | No | Standard | Swap or give-away request type. | SWAP |
swap.requester_id |
integer |
Required | No | Standard | Requesting employee ID. | 42 |
swap.requester_name |
string |
Required | No | Standard | Requesting employee display name. | Jordan Lee |
swap.requester_shift_id |
integer |
Required | No | Standard | Requester shift ID. | 5512 |
swap.requester_shift_date |
date |
Required | No | Standard | Requester shift date. | 2026-08-22 |
swap.requester_shift_time |
string |
Required | No | Standard | Requester shift time range. | 08:00 - 16:00 |
swap.target_id |
integer |
Required | Yes | Standard | Receiving employee ID. | 56 |
swap.target_name |
string |
Required | Yes | Standard | Receiving employee display name. | Taylor Morgan |
swap.target_shift_id |
integer |
Required | Yes | Standard | Target shift ID for an exchange. | 5520 |
swap.target_shift_date |
date |
Required | Yes | Standard | Target shift date for an exchange. | 2026-08-23 |
swap.target_shift_time |
string |
Required | Yes | Standard | Target shift time range for an exchange. | 12:00 - 20:00 |
swap.status |
enum |
Required | No | Standard | New coverage-request status. | APPROVED |
previous_status |
enum |
Required | No | Standard | Status before approval. | TARGET_ACCEPTED |
approved_by |
integer |
Required | Yes | Standard | Reviewing user ID. | 7 |
approved_at |
date-time |
Required | No | Standard | ISO 8601 approval timestamp. | 2026-08-20T09:05:11-05:00 |
Payload produced after a manager rejects a shift swap or shift-board pickup. Free-text notes are intentionally excluded.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
swap.id |
integer |
Required | No | Standard | Coverage-request ID. | 285 |
swap.request_type |
enum |
Required | No | Standard | Swap or give-away request type. | SWAP |
swap.requester_id |
integer |
Required | No | Standard | Requesting employee ID. | 42 |
swap.requester_name |
string |
Required | Yes | Standard | Requesting employee display name when available. | Jordan Lee |
swap.requester_shift_id |
integer |
Required | No | Standard | Requester shift ID. | 5512 |
swap.requester_shift_date |
date |
Required | Yes | Standard | Requester shift date when available. | 2026-08-22 |
swap.requester_shift_time |
string |
Required | Yes | Standard | Requester shift time range when available. | 08:00 - 16:00 |
swap.target_id |
integer |
Required | No | Standard | Receiving employee ID. | 56 |
swap.target_name |
string |
Required | Yes | Standard | Receiving employee display name when available. | Taylor Morgan |
swap.target_shift_id |
integer |
Required | Yes | Standard | Target shift ID for an exchange. | 5520 |
swap.target_shift_date |
date |
Required | Yes | Standard | Target shift date for an exchange. | 2026-08-23 |
swap.target_shift_time |
string |
Required | Yes | Standard | Target shift time range for an exchange. | 12:00 - 20:00 |
swap.status |
enum |
Required | No | Standard | New coverage-request status. | REJECTED |
previous_status |
enum |
Required | No | Standard | Status before rejection. | TARGET_ACCEPTED |
rejected_by |
integer |
Required | Yes | Standard | Reviewing user ID. | 7 |
rejected_at |
date-time |
Required | No | Standard | ISO 8601 rejection timestamp. | 2026-08-20T09:22:05-05:00 |
Payload produced when an employee completes all onboarding tasks currently available to them. Task titles, form answers, signatures, documents, and tax or identity data are excluded.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
employee.id |
integer |
Required | No | Standard | Employee ID. | 42 |
employee.display_name |
string |
Required | No | Standard | Employee display name. | Jordan Lee |
employee.manager_id |
integer |
Required | Yes | Standard | Assigned manager employee ID. | 9 |
employee.hire_date |
date |
Required | No | Standard | Employee hire date, or an empty string. | 2026-08-24 |
completion.completed_task_id |
integer |
Required | No | Standard | Task whose completion closed the currently available checklist. | 812 |
completion.available_task_count |
integer |
Required | No | Standard | Currently unlocked onboarding tasks. | 7 |
completion.completed_task_count |
integer |
Required | No | Standard | Completed currently unlocked tasks. | 7 |
completion.completed_at |
date-time |
Required | No | Standard | ISO 8601 checklist completion timestamp. | 2026-08-20T11:15:00-05:00 |
actor.type |
enum |
Required | No | Standard | EMPLOYEE or USER. | EMPLOYEE |
actor.id |
integer |
Required | Yes | Standard | Employee or user ID that completed the final task. | 42 |
Payload produced when the primary payroll report is downloaded. It reports export totals and identifiers without including employee rows, rates, earnings, deductions, or bank details.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
export.provider |
string |
Required | No | Standard | Payroll export format/provider key. | generic |
export.company_code |
string |
Required | Yes | Sensitive | Optional external payroll company code. | ACME01 |
export.date_from |
date |
Required | No | Standard | First exported work date. | 2026-08-10 |
export.date_to |
date |
Required | No | Standard | Last exported work date. | 2026-08-23 |
export.filename |
string |
Required | No | Standard | Downloaded filename. | generic_payroll_20260810_20260823.csv |
export.format |
enum |
Required | No | Standard | Selected download format. | csv |
export.row_count |
integer |
Required | No | Standard | Employee/payroll rows exported. | 18 |
export.total_hours |
number |
Required | No | Standard | Aggregate exported hours. | 1284.5 |
export.regular_hours |
number |
Required | No | Standard | Aggregate regular hours. | 1200 |
export.overtime_hours |
number |
Required | No | Standard | Aggregate overtime hours. | 84.5 |
export.double_overtime_hours |
number |
Required | No | Standard | Aggregate double-overtime hours. | 0 |
export.missing_payroll_id_count |
integer |
Required | No | Standard | Rows missing an external payroll identifier. | 0 |
exported_by |
object |
Required | Yes | Standard | Authenticated user that downloaded the export. | {"id":7,"name":"Morgan Ellis"} |
exported_at |
date-time |
Required | No | Standard | ISO 8601 export timestamp. | 2026-08-20T14:05:00-05:00 |
Payload produced when a pending tip pool is approved. It includes the pool-level amount and allocation count, but excludes employee allocations and review notes.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
tip_pool.id |
integer |
Required | No | Standard | Tip-pool ID. | 284 |
tip_pool.pool_date |
date |
Required | No | Standard | Business date represented by the pool. | 2026-08-19 |
tip_pool.work_location_id |
integer |
Required | Yes | Standard | Work-location relationship ID. | 3 |
tip_pool.location |
string |
Required | No | Standard | Resolved work-location label, or an empty string. | Main Office |
tip_pool.shift_label |
string |
Required | No | Standard | Optional shift/daypart label, or an empty string. | Dinner |
tip_pool.total_tips |
number |
Required | No | Sensitive | Approved pool-level tip amount. | 842.35 |
tip_pool.split_method |
string |
Required | No | Standard | Allocation method. | HOURS_WORKED |
tip_pool.payroll_earning_code |
string |
Required | No | Standard | Payroll earning code assigned to the pool. | TIPS |
tip_pool.source_type |
string |
Required | No | Standard | Pool construction source. | POLICY |
tip_pool.allocation_count |
integer |
Required | No | Standard | Employees allocated by the approved pool. | 12 |
tip_pool.status |
enum |
Required | No | Standard | New pool status. | APPROVED |
approved_by |
integer |
Required | Yes | Standard | Reviewing user ID. | 7 |
approved_at |
date-time |
Required | No | Standard | ISO 8601 approval timestamp. | 2026-08-20T15:20:00-05:00 |
Payload queued from Integrations Hub to verify endpoint configuration and delivery.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
source |
string |
Required | No | Standard | AppyShift surface that queued the test. | settings.integrations |
queued_by |
integer |
Required | Yes | Standard | User ID that queued the test. | 7 |
queued_at |
date-time |
Required | No | Standard | ISO 8601 queue timestamp. | 2026-08-19T14:42:10-05:00 |
Error envelope returned by protected API resources.
| Field | Type | Presence | Nullable | Classification | Description | Example |
|---|---|---|---|---|---|---|
error.code |
string |
Required | No | Standard | Stable machine-readable error code. | missing_scope |
error.message |
string |
Required | No | Standard | Human-readable explanation safe to log. | API token does not include the required scope. |
error.request_id |
string |
Required | No | Standard | Correlation ID for support and access-log lookup. | req_xxx |
Request base columns and select formats separately. The response uses the advertised output field, keeping names, dates, phone numbers, and money consistent with AppyShift.
| Field type | Format values | Example |
|---|---|---|
| Employee name | default, legal, last_first, preferred, initials | Lee, Jordan |
| Date | default, iso, us, european, long, month_day | 05/01/2026 |
| Phone | default, formatted, digits | (555) 123-4567 |
| Number | default, number, currency | $1,234.50 |
| Checkbox | default, checkmark | Yes |
Scopes are assigned to the OAuth client and can be narrowed again when requesting a token.
| Scope | Access | Classification |
|---|---|---|
employee_fields:read | List reportable employee field definitions and formats. | Standard |
employee_fields:write | Partially update API-exposed custom field values. | Standard |
employee_fields.sensitive:write | Update custom fields classified as sensitive. | Admin grant only |
reports:read | List report datasets and saved report definitions. | Standard |
reports:run | Run saved and ad-hoc reports. | Standard |
reports.sensitive:read | Include compensation, birth date, address, and other sensitive HR fields. | Admin grant only |
employees:read | Read the standard employee roster endpoint. | Standard |
employees:write | Update an employee payroll ID through the existing endpoint. | Standard |
credentials:read | Read employee certifications and licenses. | Standard |
timesheets:read | Read individual time entries. | Standard |
schedules:read | Read scheduled shifts. | Standard |
departments:read | Read departments and employee counts. | Standard |
positions:read | Read positions and employee counts. | Standard |
locations:read | Read work locations. | Standard |
time_off:read | Read time-off requests and balances. | Standard |
deductions:read | Read active employee deductions and employer matching amounts. | Admin grant only |
The reports.sensitive:read scope can only be granted by a Company Admin or Super Admin who also has sensitive-report export authority. The request must explicitly set include_sensitive.
Protected resource errors include a stable code, a readable message, and a request ID that can be matched to AppyShift access logs.
{
"error": {
"code": "missing_scope",
"message": "API token does not include the required scope.",
"request_id": "req_xxx"
}
}
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_json | The JSON request body could not be parsed. |
| 400 | invalid_scope | The token request asked for a scope the client was not granted. |
| 401 | invalid_client | The OAuth client credentials were rejected. |
| 401 | invalid_bearer_token | The access token is missing, expired, invalid, or revoked. |
| 403 | missing_scope | The token does not have the scope required by the endpoint. |
| 404 | report_not_found | The requested saved report does not exist in this company. |
| 413 | request_too_large | The report request body exceeded 256 KB. |
| 422 | invalid_dataset | The requested report dataset is unavailable. |
| 422 | invalid_view | The selected resource view is not supported. |
| 422 | invalid_metadata | Report metadata is not a valid bounded flat key/value object. |
| 422 | invalid_custom_field | A custom field is inactive, non-reportable, unknown, or malformed. |
| 422 | invalid_custom_field_value | A custom field value does not match its configured type or options. |
| 429 | rate_limited | The client or IP exceeded the current request limit. |
Protected resources currently use the /api/v1 prefix. Additive response fields may appear within a version; integrations should ignore unknown properties. Breaking path, request, or response changes will use a new API version.
aps_live_ keys remain supported for existing integrations, but new clients should use OAuth.