Cancel a leave request
Cancels a request waiting for a decision, or approved leave that hasn't started (its days come back to the
balance). Leave that has started returns invalid_state: HR ends it early in the Console. leave.cancelled
fires.
Scope: attendance:manage · Plan: Pro and Enterprise in live mode; every plan in test mode.
AuthorizationBearer <token>Send Authorization: Bearer <token> on every request. The token is one of:
| Prefix | What it is | Where it may be used |
|---|---|---|
agoo_sk_live_ | Secret key, live mode | Your servers only |
agoo_sk_test_ | Secret key, test mode | Your servers only |
agoo_pk_live_ | Publishable key, live mode | Browsers and apps: create pre-registrations and bookings, read public booking types (with their intake questions) and their free slots, read the visit types open for pre-registration with their public forms. Never lists people. |
agoo_pk_test_ | Publishable key, test mode | As above, in test mode |
Admins create keys in Console → Developers → API keys and choose each key's scopes. A key is shown once. Never put a secret key in a URL, a browser or a mobile app.
Scope: attendance:manage
leave_id*stringThe leave request's ID.
^leave_[0-7][0-9a-hjkmnp-tv-z]{25}$"leave_01m4z0q2k8fv7tqz3x9c1nbe5d"Idempotency-Key*stringA UUID you generate for this operation. If you retry with the same key within 24 hours, Agoo returns the
original response instead of acting twice. While the first request is still running, a retry returns
conflict. Reusing a key with a different request returns idempotency_key_reused. Responses with
rate_limited, internal_error or unavailable aren't stored, so retry those with the same key.
uuidapplication/json- body
reason*string3 <= length <= 300The leave request, cancelled.
application/json- response
A leave request. A private type (sick and maternity by default) comes back as kind: away, without its type, reason or note.
id*LeaveRequestIdA leave request ID (TypeID with the leave prefix).
^leave_[0-7][0-9a-hjkmnp-tv-z]{25}$"leave_01m4z0q2k8fv7tqz3x9c1nbe5d"person_id*PersonIdA person ID (TypeID with the person prefix).
^person_[0-7][0-9a-hjkmnp-tv-z]{25}$"person_01kjsesxm0e4zbyvkr7bcfxbfg"type_id*|null for a private type.
^ltype_[0-7][0-9a-hjkmnp-tv-z]{25}$type_name*string"Annual leave""Away"kind*string"annual""sick""maternity""paternity""compassionate""study""unpaid""other""away"private*booleanstatus*string"pending""approved""declined""cancelled"starts_on*stringdateends_on*stringThe last day of leave.
datehalf_day*booleanhalf_day_part*|"morning""afternoon"nulldays*numberWhat it counts, in unit.
3unit*string"working_days""calendar_days"paid*booleanreason*|The person's note; null for a private type.
decision_note*|The approver's note; null for a private type.
decided_at*|date-timedecided_by*|Who decided it; null when recorded, decided through the API or approved at once.
^person_[0-7][0-9a-hjkmnp-tv-z]{25}$approval*|The approval's state; null when it needed none.
cancelled_at*|date-timecreated_at*stringdate-timeupdated_at*stringdate-timecurl -X POST 'https://api.agoo.ardent.africa/v1/leave-requests/leave_01m4z0q2k8fv7tqz3x9c1nbe5d/cancel' \ -H 'Idempotency-Key: 3f6b2a1e-8c4d-4f7a-9b2e-5d1c0a7e9f64' \ -H 'Content-Type: application/json' \ -d '{ "reason": "Plans changed"}'{ "id": "leave_01m4z0q2k8fv7tqz3x9c1nbe5d", "person_id": "person_01kjw4mg80efgb5aqbsqnxhtbh", "type_id": "ltype_01m4y8r6t0e9k2b7c5d3f1g0hj", "type_name": "Annual leave", "kind": "annual", "private": false, "status": "cancelled", "starts_on": "2026-11-16", "ends_on": "2026-11-18", "half_day": false, "half_day_part": null, "days": 3, "unit": "working_days", "paid": true, "reason": "Family visit in Ho", "decision_note": null, "decided_at": null, "decided_by": null, "approval": { "status": "cancelled", "step": null, "of": 2 }, "cancelled_at": "2026-10-15T08:30:00Z", "created_at": "2026-10-14T09:12:00Z", "updated_at": "2026-10-15T08:30:00Z"}Approve or decline a leave request POST
Approves or declines a request waiting for a decision, all its approval steps at once (your organisation's approvers decide step by step in Agoo Workspace and the Console). A decline needs a `note` the person sees; a type that can't be declined (maternity: the dates are agreed, Labour Act s.57) can only be approved; approving stays within the balance. A request that isn't waiting returns `invalid_state`. `leave.approved` or `leave.declined` fires. **Scope:** `attendance:manage` · **Plan:** Pro and Enterprise in live mode; every plan in test mode.
List a person's leave balances GET
Returns this leave year's figures for each type with a yearly balance: `entitled`, `carried` over, `taken`, `adjusted`, `expired`, the `balance`, `booked` (approved, not started) and `pending` (waiting for a decision). Private types aren't listed. **Scope:** `attendance:read` · **Plan:** Pro and Enterprise in live mode; every plan in test mode.