Developer
v1 REST API
Call Reqio's public REST API from your own backend or workflow tools: authentication, per-plan daily quotas, and the resources it exposes.
Reqio exposes a per-project REST API for backends and workflow tools that would rather call plain HTTP endpoints than speak MCP. It covers the same operations as the MCP server: backlog, conversations, requesters, notifications, widget config, and project.
Before you start
- A Reqio project on any plan
- The issueTokens capability (Owner role) to create an API key
Available on every plan
Every plan can create API keys and call v1 endpoints. The quota is what scales with plan: Free gets 100 calls a day, Pro 10,000, Scale 100,000. See Daily quota below.
Authentication
Every request needs a Bearer credential:
Request format
GET /p/{projectId}/api/v1/features HTTP/1.1
Host: reqio.app
Authorization: Bearer YOUR_CREDENTIAL- API key
- Created at Project → Settings → API keys. Pick a name, one or more scopes, and an optional expiry. The raw key is shown exactly once at creation time; only its hash is stored.
- MCP OAuth token
- The same opaque, audience-bound token issued by the OAuth authorization flow.
- CORS
- Not supported on these routes. The v1 API is for server-to-server calls, not for calling directly from a browser.
Both credential types are normalized to the same actor context before any endpoint runs, so a workflow tool can use a long-lived API key while an interactive agent uses its OAuth token, against the same API.
Scopes
The v1 API checks the same scopes as the MCP server (see OAuth authorization), plus one REST-only scope with no MCP tool equivalent:
agent:claimscopebacklog:write creates a new feature request via the API, and also backs the MCP create_feature tool (see Available tools), so the same scope gates feature creation on both surfaces. requesters:read and notifications:read back both the /requesters and /notifications REST resources below and the MCP list_requesters / list_notifications tools: the same scope, checked by both surfaces.
An API key can only be issued with scopes up to what the issuing user's role and the project's plan allow, the same rule that governs OAuth consent.
Daily quota
Every v1 call is metered against the project owner's plan, scoped per project (all of a project's API keys and OAuth clients share one counter). The quota resets at 00:00 UTC.
FreeplanProplanScaleplanThis is a separate quota from the MCP agent quota: MCP is for an interactive agent session and never polls, while the v1 API is what scheduled jobs like the GitHub agent loop call on a timer, spending a request whether or not there was anything to do.
Quota errors
If the quota is exhausted, every endpoint returns the same error, regardless of which resource you called:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
{
"error": {
"code": "API_QUOTA_EXCEEDED",
"message": "Daily API request limit reached for this project. It resets at 00:00 UTC. Upgrade for a higher limit."
}
}The quota check runs after authentication and scope checks, so an unauthorized or forbidden call never burns a slot.
One deliberate exception
POST /agent-claims never returns this 429, on any plan, at any usage level. See Agent loop claims below for why, and what it returns instead.
Every response uses the same envelope: { "data": ... } on success, { "error": { "code", "message" } } on failure, matching the dashboard's own API error shape.
Resources
All paths are relative to https://reqio.app/p/{projectId}/api/v1.
| Resource | Methods | Scope(s) |
|---|---|---|
/features | GET, POST | backlog:read, backlog:write |
/features/{id} | GET, PATCH, DELETE | backlog:read, status:write, features:delete |
/features/{id}/comments | GET, POST | backlog:read, comments:write |
/conversations | GET | conversations:read |
/conversations/{id} | GET | conversations:read |
/conversations/{id}/messages | GET, POST | conversations:read, conversations:write |
/requesters | GET | requesters:read |
/notifications | GET | notifications:read |
/project | GET, PATCH | backlog:read, project:write |
/project/widget | GET, PATCH | widget:read, widget:write |
/agent-claims | POST | agent:claim |
PATCH /features/{id} changes status only, mirroring the MCP change_status tool. POST /conversations/{id}/messages posts a team reply, mirroring reply_conversation. Every write endpoint also re-runs assertCan against live project membership, so removing a team member or revoking a key takes effect on the very next call, with no separate invalidation step.
Agent loop claims
Available on every plan, including Free. The GitHub agent loop calls this endpoint after its branch check and before invoking a model, to reserve one unit of that project owner's monthly agent-loop quota (10 on Free, 100 on Pro, 500 on Scale, pooled per workspace on Scale). It is a claim, not a completion: the feature's first agent-events post (pr_opened or needs_context) confirms it, and an unconfirmed reservation expires after 48 hours and refunds automatically.
Request
POST /p/{projectId}/api/v1/agent-claims HTTP/1.1
Host: reqio.app
Authorization: Bearer YOUR_CREDENTIAL
Content-Type: application/json
{
"featureId": "clx1a2b3c4d5",
"dryRun": false
}Always HTTP 200
Every outcome below, including a spent-out quota, returns 200. The action reads claimed and reason from the body; it never has to branch on a status code. This is deliberate: a scheduled job that sees a non-2xx from Reqio has no way to tell "you're out of quota" apart from "Reqio is down," and would fail its own CI run either way. So the endpoint never puts that decision in the transport layer.
There are five response shapes:
Claimed, first time this feature has been claimed
{ "claimed": true, "alreadyCounted": false, "quota": { "used": 4, "limit": 10, "resetsAt": "2026-09-01T00:00:00.000Z" } }Repeat claim on an already-claimed feature - free of charge
{ "claimed": true, "alreadyCounted": true, "quota": { "used": 4, "limit": 10, "resetsAt": "2026-09-01T00:00:00.000Z" } }Quota exhausted for this period
{ "claimed": false, "reason": "loop_quota_exhausted", "quota": { "used": 10, "limit": 10, "resetsAt": "2026-09-01T00:00:00.000Z" } }The project's agent is paused (Settings toggle)
{ "claimed": false, "reason": "agent_paused", "quota": { "used": 4, "limit": 10, "resetsAt": "2026-09-01T00:00:00.000Z" } }dryRun: true - validates scope and reads quota, reserves nothing
{ "claimed": false, "reason": "dry_run_ok", "quota": { "used": 4, "limit": 10, "resetsAt": "2026-09-01T00:00:00.000Z" } }On any claimed: false, the generated workflow skips that candidate, writes one line to the job summary, does not invoke the model, and exits 0. Nothing in your CI ever goes red because you ran out of agent loops.
- Repeat claims
- A repeat claim on a feature already claimed this period returns
alreadyCounted: trueand never spends a second unit, so draft-PR question rounds and resumed runs don't double-count. - Reset
- Calendar month UTC on Free. Your Dodo billing anchor date on Pro and Scale.
- Pooling
- Counted per owner workspace, not per project, so a Scale account running several projects draws from one shared 500.
- What's never metered
- Status changes and the notification that reaches the reporter are never counted here, on any plan. See the GitHub agent loop for the quota by plan and what happens at the ceiling.
Creating a key
Open API keys settings
Go to Project → Settings → API keys.
Create the key
Click Create key, give it a name, pick the scopes it needs, and optionally set an expiry date.
Copy the raw key
Copy the raw key immediately. Reqio only stores its hash and cannot show it again.
Revoke when needed
Revoke a key at any time from the same page. A revoked key is rejected on its very next use.
Only the project Owner can create or revoke API keys, the same issueTokens capability that gates MCP token issuance.