Docs
API referenceTimesheets

Approve a timesheet

Preview· P9
POST
/timesheets/{timesheet_id}/approve

Approves a timesheet whose period has ended, every remaining approval step at once (your organisation's approvers approve step by step in Agoo Workspace and the Console), and locks it. A timesheet still waiting for the person to confirm it is sent for approval first. Returns invalid_state while something is left to sort out (a missing clock-out, a break not ended, extra time or leave waiting for a decision, a punch waiting for review, or days still being worked out), for a period still running, and for one approved already. timesheet.approved fires.

Scope: attendance:manage · Plan: Pro and Enterprise in live mode; every plan in test mode.

Authorization

headerAuthorizationBearer <token>

Send Authorization: Bearer <token> on every request. The token is one of:

PrefixWhat it isWhere it may be used
agoo_sk_live_Secret key, live modeYour servers only
agoo_sk_test_Secret key, test modeYour servers only
agoo_pk_live_Publishable key, live modeBrowsers 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 modeAs 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

Path Parameters

timesheet_id*string

The timesheet's ID.

Match^ts_[0-7][0-9a-hjkmnp-tv-z]{25}$
Example"ts_01m5a2b3c4d5e6f7g8h9jkmnpq"

Header Parameters

Idempotency-Key*string

A 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.

Formatuuid

Response Body

The timesheet, approved and locked.

application/json
  1. response

One person's timesheet for one period. Approved is locked: its days and totals don't change until it's reopened.

id*TimesheetId

A timesheet ID (TypeID with the ts prefix).

Match^ts_[0-7][0-9a-hjkmnp-tv-z]{25}$
Example"ts_01m5a2b3c4d5e6f7g8h9jkmnpq"
person_id*PersonId

A person ID (TypeID with the person prefix).

Match^person_[0-7][0-9a-hjkmnp-tv-z]{25}$
Example"person_01kjsesxm0e4zbyvkr7bcfxbfg"
period*
status*string

open while its period runs; to_confirm while the person is asked to confirm it; to_approve in approval (or waiting to lock itself where your organisation approves none); approved and locked.

Value in"open""to_confirm""to_approve""approved"
round*integer

Each time it goes for approval again (sent back or reopened) is a new round.

confirmed_at*|

When the person confirmed it, where your organisation asks them to.

Formatdate-time
submitted_at*|
Formatdate-time
approved_at*|
Formatdate-time
approved_by*|

Who approved its last step; null when approved through the API or by Agoo.

Match^person_[0-7][0-9a-hjkmnp-tv-z]{25}$
approved_via*|

auto: it locked itself, or nobody else could approve it.

Value in"person""api""auto"null
locked*boolean
reopened_at*|
Formatdate-time
reopen_reason*string|null
changed_after_lock*boolean

Something arrived after it was locked (an offline punch, a holiday) that isn't counted until it's reopened.

totals*

What the period adds up to, from each day as Agoo worked it out. Times in seconds, breaks and lateness in minutes, days as counts.

approval*|

The current round's approval; null when there's none.

created_at*string
Formatdate-time
updated_at*string
Formatdate-time
curl -X POST 'https://api.agoo.ardent.africa/v1/timesheets/ts_01m5a2b3c4d5e6f7g8h9jkmnpq/approve' \  -H 'Idempotency-Key: 3f6b2a1e-8c4d-4f7a-9b2e-5d1c0a7e9f64'
{  "id": "ts_01m5a2b3c4d5e6f7g8h9jkmnpq",  "person_id": "person_01kjsesxm0e4zbyvkr7bcfxbfg",  "period": {    "id": "tsp_01m5a2b3c4d5e6f7g8h9jkmnpr",    "starts_on": "2019-08-24",    "ends_on": "2019-08-24",    "payroll_on": "2019-08-24"  },  "status": "open",  "round": 0,  "confirmed_at": "2019-08-24T14:15:22Z",  "submitted_at": "2019-08-24T14:15:22Z",  "approved_at": "2019-08-24T14:15:22Z",  "approved_by": "string",  "approved_via": "person",  "locked": true,  "reopened_at": "2019-08-24T14:15:22Z",  "reopen_reason": "string",  "changed_after_lock": true,  "totals": {    "worked_seconds": 0,    "counted_seconds": 0,    "regular_seconds": 0,    "overtime_daily_seconds": 0,    "overtime_weekly_seconds": 0,    "rest_day_seconds": 0,    "holiday_seconds": 0,    "night_seconds": 0,    "extra_pending_seconds": 0,    "extra_approved_seconds": 0,    "extra_declined_seconds": 0,    "paid_break_minutes": 0,    "unpaid_break_minutes": 0,    "nursing_break_minutes": 0,    "days_worked": 0,    "holidays": 0,    "absences": 0,    "authorised_paid": 0,    "authorised_unpaid": 0,    "late_count": 0,    "late_minutes": 0,    "early_leave_count": 0,    "early_leave_minutes": 0,    "leave": [      {        "type_id": "string",        "name": "Annual leave",        "kind": "annual",        "paid": true,        "days": 0      }    ]  },  "approval": {    "status": "pending",    "step": 0,    "of": 0  },  "created_at": "2019-08-24T14:15:22Z",  "updated_at": "2019-08-24T14:15:22Z"}