Get a position
Returns one position, with who holds it now and since when.
Scope: people:read · 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: people:read
position_id*stringThe position's ID.
^pos_[0-7][0-9a-hjkmnp-tv-z]{25}$"pos_01m6h2k4q8e7r9t1v3w5x7y9za"The position.
application/json- response
A seat in your organisation, with its department, site, grade, the position it reports to, and who holds it. Positions are part of Growth, Pro and Enterprise.
id*PositionIdA position ID (TypeID with the pos prefix).
^pos_[0-7][0-9a-hjkmnp-tv-z]{25}$"pos_01m6h2k4q8e7r9t1v3w5x7y9za"object*"position""position"title*string1 <= length <= 120"Senior operations officer"department_id*|nullsite_id*|nullreports_to_id*|The position it reports to. null: none.
grade*|length <= 60"G6"fte*numberFull-time equivalent, from 0.1 to 1.
0.1 <= value <= 11status*PositionStatusfilled: someone holds it now. vacant: nobody does, and it may be filled. frozen: nobody is to be hired
for it now. closed: it no longer exists, and is kept for its history. filled and vacant follow who holds
it; frozen and closed are chosen.
"filled""vacant""frozen""closed"budgeted*booleanWhether it's in the budget.
holder_id*|The person who holds it now. null: nobody.
held_since*|Since when the holder has held it.
datecreated_at*stringdate-timeupdated_at*stringdate-timecurl -X GET 'https://api.agoohq.com/v1/positions/pos_01m6h2k4q8e7r9t1v3w5x7y9za'{ "id": "pos_01m6h1a3c5e7g9j1k3m5n7p9qr", "object": "position", "title": "Head of Operations", "department_id": "dept_01kjsd2v80e5q7m3c9x4ht6wfb", "site_id": "site_01kjpt3yw0fz0v414608h9x65s", "reports_to_id": null, "grade": "G9", "fte": 1, "status": "filled", "budgeted": true, "holder_id": "person_01kjsf3c00ecxs9b3k1hw7wq2n", "held_since": "2024-02-01", "created_at": "2026-10-12T08:30:00Z", "updated_at": "2026-10-12T08:30:00Z"}Create a position POST
Makes a position: a seat in your organisation with its department, site, grade and the position it reports to. It's `vacant` until someone holds it, which happens with a job change that sets their `position_id` (`POST /people/{person_id}/job-changes`). Positions are part of Growth, Pro and Enterprise, so in test mode an organisation on another plan gets `plan_required`. - Fires `position.created`. **Scope:** `hr:write` · **Plan:** Pro and Enterprise in live mode; Growth, Pro and Enterprise in test mode.
Update a position PATCH
Changes a position's title, department, site, grade, the position it reports to, its full-time equivalent or whether it's budgeted, or freezes, closes or reopens it. Send only the fields you want to change; `null` clears an optional one. - A position someone holds can't be frozen or closed (`invalid_state`): change their job first. - `status: vacant` reopens a frozen or closed position; it shows `filled` while someone holds it. Who holds a position is changed by a job change, never here. - Fires `position.updated`, with `previous_attributes.changed` naming what changed. **Scope:** `hr:write` · **Plan:** Pro and Enterprise in live mode; Growth, Pro and Enterprise in test mode.