External Integration
Payroll Partner
Two patterns are supported.
Push (Webhook)
Nightly job at 04:00 UTC posts locked days to the partner's endpoint:
POST https://payroll.partner/attendance/daily
Authorization: Bearer <partner-token>
Content-Type: application/json
[
{
"employee_id": "E123",
"organization_code": "ACME",
"unit_code": "ACME-BLR-01",
"date": "2026-04-01",
"status": "present",
"check_in": "09:05:00Z",
"check_out": "17:55:00Z",
"worked_minutes": 530,
"flags": ["LATE_CHECK_IN"]
}
]
Pull
Partner polls /integrations/payroll/pull:
GET /api/v1/integrations/payroll/pull?month=2026-04&org_id=1
Authorization: Bearer <partner-token>
Returns the full locked month or 409 LOCK_PENDING if the month isn't locked yet.
Billing
Billing systems receive the same payload as payroll. The billing-specific fields (rate_id, billable_minutes) live in the partner system, not here.
Webhook Signatures
Every webhook we send includes:
X-Attendance-Signature: t=1713870000,v1=3a7b...
Calculated as HMAC-SHA256(secret, "<timestamp>." + body). Partners must verify within a 5-minute window to prevent replay.
Rate Limits on Integration Endpoints
- Pull: 60 req/min per partner.
- Webhook retries: exponential backoff, 5 attempts,
Retry-Afterrespected.