Customer company admins can create API keys and webhooks in Settings › Integrations. Read APIs are read-only and do not provide personal information (mobile phone, date of birth, salary, bank account, address). All requests use HTTPS, and responses are JSON.
GET https://www.gijun.co.kr/api/v1/members Authorization: Bearer gj_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Returns 401/403 if the key has been revoked or the service is not active. Rate limit: 600 requests per minute per IP.
| Path | Description | Query |
|---|---|---|
GET /api/v1/company | Company information · usage status · seats | - |
GET /api/v1/members | Employee list (active, on leave, resigned, etc., excluding personal information) | status, department, limit(≤500), offset |
GET /api/v1/leave-requests | Leave request and approval history | from, to, status, member_id, limit, offset |
GET /api/v1/schedules | Calendar schedules (title, dates, times, author, participants; tasks excluded) | from, to, limit, offset |
GET /api/v1/holidays | Korean public holidays (by year) | year |
GET /api/v1/leave-balances | Annual leave remaining by member | year, limit, offset |
GET /api/v1/attendance | Clock-in/out records | from, to, member_id, limit, offset |
{ "data": [ { "id": "…", "name": "Hong Gil-dong", "department": "Engineering team", "status": "active", "joined_at": "2026-01-02T00:00:00+00:00" } ],
"total": 42, "limit": 100, "offset": 0 }When an event occurs, we POST JSON to the registered URL. If there is no 2xx response, we retry at intervals of 1 minute, 5 minutes, 30 minutes, 2 hours, and 12 hours (6 times total), and webhooks that fail 20 consecutive times are automatically disabled. The same event may be delivered twice, so delivery_id filter out duplicates with it.
| Event | Occurred at | Body key |
|---|---|---|
member.joined | Employees joined (signup approved · invitation accepted · directly registered) | member |
member.resigned | Process resignation | member |
member.on_leave | Process leave of absence | member |
member.returned | Return from leave of absence | member |
leave.requested | Leave request submitted | leave_request |
leave.approved | Leave finally approved | leave_request |
leave.rejected | Leave rejected | leave_request |
leave.cancelled | Leave canceled | leave_request |
attendance.clock_in | Clock-in record | work_session |
attendance.clock_out | Clock-out record | work_session |
POST https://example.com/webhooks/gijun
Content-Type: application/json
X-Gijun-Event: leave.approved
X-Gijun-Delivery: 5f0c…
X-Gijun-Signature: t=1788660000,v1=3f1a… // HMAC-SHA256(secret, `${t}.${rawBody}`)
{ "event": "leave.approved", "company_id": "…", "occurred_at": "2026-09-06T02:00:00Z", "delivery_id": "5f0c…", "attempt": 1,
"leave_request": { "id": "…", "member_id": "…", "member_name": "Hong Gil-dong", "start_date": "2026-09-10", "end_date": "2026-09-11", "days_used": 2, "status": "approved" } }import { createHmac, timingSafeEqual } from 'node:crypto'
export function verify(rawBody, signatureHeader, secret) {
const t = /t=(\d+)/.exec(signatureHeader)?.[1], v1 = /v1=([a-f0-9]+)/.exec(signatureHeader)?.[1]
if (!t || !v1 || Math.abs(Date.now() / 1000 - Number(t)) > 300) return false // Reject requests older than 5 minutes
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex')
return expected.length === v1.length && timingSafeEqual(Buffer.from(expected), Buffer.from(v1))
}Contact: support@gijun.co.kr · Write APIs (such as registering leave requests) are provided by priority upon request.