Skip to content

REST API Reference

The same roster data the MCP server exposes, over plain HTTP. Use this for dashboards, scripts and integrations that are not AI agents.

Base URL

https://app.manageroster.com/api/v1

Authentication

Bearer token in the Authorization header. Create one in Settings → API & MCP — see MCP server setup, the same tokens work for both.

bash
curl -s https://app.manageroster.com/api/v1/me \
  -H 'Authorization: Bearer YOUR_TOKEN' \
  -H 'Accept: application/json'

Every token is bound to one workspace. There is no workspace parameter on any endpoint — the token determines it.

Responses

Success responses wrap the payload in data:

json
{ "data": { "…": "…" } }

Errors return an error object and a matching HTTP status:

json
{
  "error": {
    "code": "insufficient_scope",
    "message": "This token is missing the required scope. Needs one of: leaves:read. It currently has: agents:read.",
    "required_scopes": ["leaves:read"],
    "token_scopes": ["agents:read"]
  }
}
StatusCodeMeaning
401unauthenticatedToken missing, invalid, revoked or expired
403forbiddenWorkspace API disabled, or the user is no longer a member
403insufficient_scopeToken lacks the scope, or is read-only and you attempted a write
422Validation failed. errors names the fields
404Record not found in this workspace

Date ranges

Endpoints taking a range accept either explicit dates or a relative period.

ParameterValues
from / toYYYY-MM-DD. Both required together; overrides period
periodtoday, next_week, this_month, next_month. Defaults to the current week

Ranges longer than 366 days are truncated.

Endpoints

GET /me

Who the token acts as, its workspace, and its effective scopes. No scope required — use it to verify a token.

json
{
  "data": {
    "user": { "id": 4, "name": "Rahim Chowdhury", "email": "…" },
    "workspace": { "id": 2, "name": "xCloud Support", "timezone": "Asia/Dhaka", "agent_count": 8, "features": {}, "your_role": "owner" },
    "token": { "name": "Claude Code — laptop", "scopes": ["schedule:read", "leaves:read"], "is_read_only": true, "last_used_at": "2026-09-06T10:22:41+00:00" }
  }
}

GET /workspace

Scope: workspace:read

Workspace name, timezone, active agent count and enabled feature modules.


GET /agents

Scope: agents:read

QueryDescription
active_onlytrue (default) or false

Returns id, name, active, colour, holiday group, office days and off days.


GET /agents/available

Scope: schedule:read

Agents not rostered and not on approved leave for a date.

QueryDescription
dateRequired. YYYY-MM-DD
hour023. Omit to check the whole day

Agents on a public holiday are included with on_public_holiday: true rather than filtered out — they are often available for overtime, and you want that context before asking.


GET /schedule

Scope: schedule:read

QueryDescription
from / to / periodDate range
agent_idLimit to one agent

Consecutive hours for the same agent are collapsed into blocks. end_hour is exclusive.

json
{
  "data": {
    "from": "2026-09-07", "to": "2026-09-13",
    "days": [
      { "date": "2026-09-07",
        "blocks": [
          { "agent_id": 3, "agent_name": "Nadia", "start_hour": 9, "end_hour": 17, "hours": 8, "is_ot": false, "shift_type": "morning_day" }
        ] }
    ],
    "total_assigned_hours": 112
  }
}

GET /schedule/coverage

Scope: schedule:read

Uncovered hours as contiguous ranges, plus an overall coverage percentage.

QueryDescription
from / to / periodDate range
min_agentsMinimum agents for an hour to count as covered. Default 1
json
{
  "data": {
    "from": "2026-09-07", "to": "2026-09-13",
    "min_agents": 1,
    "gaps": [ { "date": "2026-09-08", "start_hour": 2, "end_hour": 6, "hours": 4, "assigned": 0, "required": 1 } ],
    "gap_count": 1,
    "uncovered_hours": 4,
    "coverage_percent": 97.6
  }
}

POST /schedule

Scope: schedule:write

json
{ "agent_id": 3, "date": "2026-09-08", "start_hour": 9, "end_hour": 17, "is_ot": false, "notes": null }

Returns 201. Refuses with 422 if the agent is on approved leave or already rostered in those hours, naming the conflict.

For an overnight shift, make two calls — one ending at hour 24, one starting at hour 0 on the next date.


DELETE /schedule

Scope: schedule:write

Same body as POST minus is_ot and notes. Returns the number of hours removed.


GET /leaves

Scope: leaves:read

QueryDescription
from / to / periodDate range
statuspending, approved, rejected
agent_idLimit to one agent

Matches on overlap, so leave starting before the range and running into it is included.


POST /leaves

Scope: leaves:write

json
{ "agent_id": 3, "type": "annual", "start_date": "2026-09-14", "end_date": "2026-09-18", "notes": null }

type is one of annual, sick, casual, maternity. status defaults to pending.

Refuses with 422 on overlapping leave. Returns a warnings array — not an error — when the agent is already rostered during the requested dates, since those shifts need reassigning.


PATCH /leaves/{id}

Scope: leaves:write

json
{ "status": "approved" }

GET /holidays

Scope: holidays:read

QueryDescription
from / to / periodDate range. Defaults to the current month
groupHoliday group code, e.g. BD, PH

Each holiday includes affects_agents — the agents in that holiday group — because groups are per-agent and one workspace can run several national calendars.


GET /ot-events

Scope: ot:read

QueryDescription
statusdraft, active, closed

GET /ot-events/{id}/coverage

Scope: ot:read

Slot-by-slot volunteer coverage for one OT event, and uncovered_slots.


GET /work-reports/missed

Scope: reports:read

QueryDescription
from / to / periodDate range
agent_idLimit to one agent

Only counts dates where the agent was actually rostered.

Rate limits

The default API throttle is 60 requests per minute per token. Exceeding it returns 429 with a Retry-After header.

Examples

Who is on leave next week

bash
curl -s 'https://app.manageroster.com/api/v1/leaves?period=next_week&status=approved' \
  -H 'Authorization: Bearer YOUR_TOKEN'

Which slots are empty this week

bash
curl -s 'https://app.manageroster.com/api/v1/schedule/coverage?period=this_week' \
  -H 'Authorization: Bearer YOUR_TOKEN'

Assign a night shift crossing midnight

bash
curl -s -X POST https://app.manageroster.com/api/v1/schedule \
  -H 'Authorization: Bearer YOUR_TOKEN' -H 'Content-Type: application/json' \
  -d '{"agent_id":3,"date":"2026-09-08","start_hour":22,"end_hour":24}'

curl -s -X POST https://app.manageroster.com/api/v1/schedule \
  -H 'Authorization: Bearer YOUR_TOKEN' -H 'Content-Type: application/json' \
  -d '{"agent_id":3,"date":"2026-09-09","start_hour":0,"end_hour":6}'

Built with ❤️ for support teams worldwide.