Restivity API
Quick Start
This page is the reference. The Redoc viewer below is generated from the same schemas the API validates with; the rate limits and the plan requirement in sections 5 and 6 are read from the code that enforces them. For the step-by-step connection flow see Connect an agent; for the OAuth details an agent reads on its own, /auth.md and /llms.txt.
1. Authentication — OAuth 2.0 + PKCE
Every /api/v1/* endpoint requires a Bearer token from the standard authorization_code grant with PKCE (RFC 7636). There is no API-key flow. Discover the OAuth server at /.well-known/oauth-authorization-server; register a client at POST /api/oauth/register; exchange the code at POST /api/oauth/token. Access tokens are signed JWTs (alg: ES256) verifiable with /api/oauth/jwks and expire in 1 hour. Refresh tokens rotate on each refresh; replaying a used refresh token revokes ALL of the client's tokens (RFC 6749 §10.4).
2. Scope model
Scopes are least-privilege. Each resource exposes :read and :write variants — tasks:read, tasks:write, projects:read, projects:write, pomodoro:read, pomodoro:write, profile:read, profile:write. The effective scope on a token is the intersection of (a) what the user consented to and (b) what the registered client requested. Calls outside the granted scope return 403 with WWW-Authenticate: Bearer error="insufficient_scope".
3. Pagination convention
List endpoints paginate via opaque cursor. Request: ?limit=<1-100, default 50>&cursor=<opaque>. Response wraps rows in { data: […], next_cursor: string | null }. next_cursor is null when the current page is the last one — the nullability IS the "has-more" signal, no separate boolean. Filter via documented query parameters; multiple filters AND together.
4. Error shape
Every error response is RFC 9457 problem-details (Content-Type: application/problem+json). The body has { type, title, status, detail, instance } — plus scope_required on 403 and retry_after on 429. type is the issuer origin + /errors/<slug>: 400 invalid_request, 401 invalid_token, 403 insufficient_scope, 404 not_found (also for soft-deleted), 422 unprocessable, 429 rate_limited (with Retry-After), 500 internal, 503 service_unavailable.
5. Rate limits
Per user, per UTC hour, three tiers by HTTP verb. The values below are the ones this deployment enforces.
| Tier | Requests / hour | Counts |
|---|---|---|
read | 1000 | GET, HEAD |
write | 200 | POST, PATCH, PUT |
delete | 50 | DELETE |
The token endpoint (POST /api/oauth/token) has its own gate: 60 requests per source IP per minute. Over budget it answers 429 with the OAuth error slow_down and Retry-After — wait, then retry the same request.
Every agent-authenticated response carries X-RateLimit-Tier as <tier>:<count>/<limit>. Over budget, the API answers 429 problem-details (type …/errors/rate_limited) with Retry-After (seconds to the top of the hour) and retry_after in the body. Back off until then; the counter resets every hour.
6. Plan requirement
Connecting an external agent — REST /api/v1/* and MCP /api/mcp — is a paid feature. A token is minted for any account; the entitlement is checked on every call.
| Plan | Agent API |
|---|---|
| Free | Not included |
| Pro | Included |
| Team | Included |
A paid Team seat unlocks the agent API on a free personal plan too (the entitlement unions across memberships). Without it, an authenticated call gets 403 problem-details with type …/errors/upgrade_required and an upgrade_url pointing at /pricing. It is a 403, not a 401: do not restart the OAuth flow — show the upgrade link.
7. Beyond CRUD
Every resource exposes list / create / get / update / delete / restore. These operations do more; each has an MCP tool sibling with the same input and output.
POST /focus/finish— Finish working on a task: close the timer, comment, set the status — in one call. (tasks:write)POST /focus/start— Start working on a task: in progress + one work session, in one call. (tasks:write)GET /profile— Fetch the authenticated user profile. (profile:read)PATCH /profile— Update writable profile fields. (profile:write)DELETE /project-statuses/{id}— Delete a custom status (hard delete). (projects:write)PATCH /project-statuses/{id}— Rename, recolor or recategorize a custom status. (projects:write)GET /projects/{id}/statuses— List a project's custom statuses. (projects:read)POST /projects/{id}/statuses— Add a custom status to a project. (projects:write)POST /projects/{id}/statuses/reorder— Reorder a project's custom statuses. (projects:write)POST /projects/agent-inbox— Get or create the workspace's Agent findings inbox. (projects:write)PATCH /tasks/{id}/recurrence/rule— Edit a recurring master's rule (materialized model). (tasks:write)POST /tasks/{id}/recurrence/skip— Skip the occurrence a reminder is on (reminder_only model). (tasks:write)POST /tasks/batch-update— Apply one patch to up to 50 tasks atomically. (tasks:write)POST /tasks/search— Full-text search tasks. (tasks:read)GET /tasks/today— Today's focus list. (tasks:read)
Same handlers serve REST, MCP (/api/mcp), and the in-browser WebMCP read-only tools — see /.well-known/mcp/server-card.json for the MCP transport details.
Interactive OpenAPI 3.1 reference rendered with Redoc.