Skip to content

Admin API

All admin endpoints require executive access level.

List all users with linked people data.

Response:

{
"users": [
{
"id": "uuid",
"email": "jane@dotcollective.com.au",
"name": "Jane Doe",
"access_level": "manager",
"person_id": "people-uuid-or-null",
"productive_id": "12345-or-null",
"xero_employee_id": "xero-guid-or-null"
}
]
}

Update a user’s access level, template assignments, and employment fields.

Request:

{
"access_level": "manager",
"onboarding_template_id": "tpl-uuid",
"scorecard_template_id": "tpl-uuid",
"review_template_id": "tpl-uuid",
"employment_status": "active",
"employment_basis": "full_time",
"location": "Melbourne",
"start_date": "2023-01-15"
}

All fields are optional. Validated enums: access_level (executive/head/manager/lead/employee), employment_status (active/terminated/on_leave), employment_basis (full_time/part_time/casual/contractor), gender (male/female/non-binary/not_stated).

Response: { "user": { ... } }

Delete a user. Cannot delete yourself.

Response: { "ok": true }

Bulk sync users from Google Workspace Directory API. Creates new users and updates existing users’ name, picture, and job title. Auto-links unlinked people records by email.

Response:

{
"ok": true,
"created": 2,
"updated": 15,
"linked": 1,
"total": 17
}

Bulk sync all active people from Productive. Upserts into people table, resolves manager hierarchy, syncs squads, and removes inactive records.

Response:

{
"ok": true,
"synced": 25,
"matched_users": 18
}

Bulk auto-link unlinked people to Xero employees by name/email matching (score >= 80). Does not trigger payroll data sync.

Response:

{
"ok": true,
"linked": 5,
"total": 20
}

Sync a single user across all connected platforms:

  1. Google: Re-fetches profile (name, picture, job title) from Directory API
  2. Productive: Re-fetches person data (name, email, title, avatar) if linked
  3. Xero: Triggers payroll data refresh in the background via waitUntil if linked

Response:

{
"ok": true,
"synced": ["google", "productive", "xero"]
}

The synced array lists which providers were successfully triggered. Xero runs in the background — the response returns immediately.

GET /api/admin/users/:id/productive-matches

Section titled “GET /api/admin/users/:id/productive-matches”

Find matching unlinked people records for a user by name/email scoring. If exactly one high-confidence match (score >= 80) is found, auto-links immediately.

Response:

{
"matches": [
{
"person_id": "people-uuid",
"first_name": "Jane",
"last_name": "Doe",
"email": "jane@dotcollective.com.au",
"productive_id": "12345",
"confidence": "exact_email",
"score": 100
}
],
"auto_linked": true,
"person_id": "people-uuid"
}

Confidence levels: exact_email (100), exact_name (80), partial_name (40).

Manually link a user to a people record.

Request: { "person_id": "people-uuid" }

Response: { "ok": true }

Returns 409 if the person is already linked to another user.

List all squads with their members (derived from people.squad column).

Response:

{
"squads": [
{
"id": "uuid",
"name": "Engineering",
"members": [
{ "squad_name": "Engineering", "user_id": "uuid", "name": "Jane Doe", "email": "jane@..." }
]
}
]
}

List all tool permission grants.

Response: { "permissions": [{ "tool": "people", "access_level": "manager", "can_view": true, "can_update": false, "can_manage": false }] }

Bulk update tool permissions.

Request:

{
"permissions": [
{ "tool": "people", "access_level": "manager", "can_view": true, "can_update": true, "can_manage": false }
]
}

Response: { "ok": true }