REST API · For developers
featury over plain HTTP
Everything featury exposes to agents is also a versioned REST API: discover workspaces and projects, read the feature inventory and the complete change feed, file and groom requests, and ask the codebase agent: one personal API key, a Bearer header, JSON back.
1. Create an API key
In the app, go to Account → API keys → Create API key. The full key is shown only once. Store it somewhere safe. Only its hash is kept server-side, so it can't be recovered later.
A key acts as you: the agent works with your identity and your exact permissions in every workspace you belong to, no more, no less. Revoke a key from the same page the moment it leaks.
2. Conventions
All URLs are relative to your API origin (self-hosted? use your own):
https://api.featury.appResponses always come in an envelope: { "data": … } on success, { "error": { "code", "message" } } on failure. Status codes are plain: 400 for a malformed call, 401 for a missing or revoked key, 403 when your role can't reach the resource, 404 when it doesn't exist.
Every workspace and project parameter accepts the slug or the id: the same slugs you see in the app's URLs. And a key acts as its owner: each endpoint sees exactly what you can see in the app, no more.
Optional attribution: send an X-Featury-Agent header (or bind an agent to the key when you mint it) and everything the key does shows as “{agent} · via you” instead of just you. Without it, featury still picks up the client's own name when it can.
3. Changes
The complete internal feed of classified changes: every item carries visibility: PUBLIC | INTERNAL, including the internal entries that never reach the curated public changelog at /feed/{workspace}/{project}.json. Defaults to 50 items, max 200.
| Endpoint | What it does |
|---|---|
| GET /v1/changes | Classified changes, newest first. Filter by kind, impactSurface, from/to date; paginate with limit/offset |
curl -H "Authorization: Bearer fk_…" \
"https://api.featury.app/v1/changes?workspace=acme&project=web&limit=50"4. Requests
Bugs and feature asks, end to end. Without a status filter, the list returns only the live lanes; repeat the parameter to filter by several. BUILDING and SHIPPED stay derived from real code signals. You can't set them by hand, same rule as in the app.
| Endpoint | What it does |
|---|---|
| GET /v1/requests | List requests. Filters: status, size, impact (each repeatable), kind, horizon, search; paginate with limit/offset. Compact rows carry updatedAt, shippedAt and area |
| GET /v1/requests/:id | Full request detail: journey, comments, spec artifacts, reality read |
| POST /v1/requests | File a request ({ workspace, project, kind, title, body?, severity? }). Goes through the standard triage |
| PATCH /v1/requests/:id | Groom a request: title, body, severity, and horizon/size/fit overrides |
| POST /v1/requests/:id/status | Move a request through the manual lanes. { status, note?, declinedReason? } |
| POST /v1/requests/:id/comments | Comment on a request ({ body }). Notifies participants; @Name mentions ping |
curl -X POST "https://api.featury.app/v1/requests" \
-H "Authorization: Bearer fk_…" \
-H "Content-Type: application/json" \
-d '{"workspace":"acme","project":"web","kind":"BUG","title":"Export button returns 500"}'5. Features & discovery
Start here: list your workspaces, then the projects inside one, then the living feature inventory of a project.
| Endpoint | What it does |
|---|---|
| GET /v1/workspaces | The workspaces you belong to: id, name, slug, your role |
| GET /v1/projects | The projects you can access in a workspace |
| GET /v1/features | The project's living feature inventory |
curl -H "Authorization: Bearer fk_…" \
"https://api.featury.app/v1/features?workspace=acme&project=web"6. Ask the codebase
One question in, a grounded answer out. Non-streaming, so expect a long call. Pass the returned conversationId back to continue the thread. Spends the workspace AI budget, like a chat message in the app.
| Endpoint | What it does |
|---|---|
| POST /v1/ask | Ask the codebase agent: { question, conversationId? } → { data: { answer, conversationId, sources } }. `sources` names the repo docs and features the turn actually read. |
curl -X POST "https://api.featury.app/v1/ask" \
-H "Authorization: Bearer fk_…" \
-H "Content-Type: application/json" \
-d '{"workspace":"acme","project":"web","question":"How does billing retry failed payments?"}'7. Public changelog (no key needed)
Every product's published changelog is served logged-out, in four formats, from a stable address, and it answers any origin, so your own site can fetch the JSON and build a page from it. This is the call behind featury.app/changelog.
| Endpoint | What it does |
|---|---|
| GET /feed/{ws}/{proj}.{html|json|md|xml} | The index. Newest first, 20 editions to a page |
| GET /feed/{ws}/{proj}.{ext}?before={n} | Older pages; the JSON's next carries the link |
| GET /feed/{ws}/{proj}/{n}.{html|json|md} | One edition's permanent address |
| GET /feed/{ws}/{proj}/og.png · /{n}/og.png | Share cards: the feed's, and one edition's |
curl https://api.featury.app/feed/featury/featury.json8. Good to know
- BUILDING and SHIPPED are derived from real code signals and can never be set by hand. Same rule as in the app.
- Cite a request's refCode in a commit or PR message ("Closes idea/dark-mode", "Fixes bug/login-white-screen") and the ticket auto-ships and notifies its requester.
- Mutations behave exactly like the in-app actions (journey events, notifications) and are attributed to you.
- Want your coding agent to use all of this without writing code? That's the MCP endpoint. Same keys, same capabilities, tool-shaped. MCP docs →