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
422—Validation failed. errors names the fields
404—Record 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
hour0–23. 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.