Very Simple Projects
One token. One project. File, report, never delete.
A token opens exactly one project. There is no project parameter. Tickets are numbered 1, 2, 3, the way the person says it. You file, you write in the thread, you change status. You never delete.
Base URL: https://verysimpleprojects.com/api/v1.
Auth: Authorization: Bearer TOKEN.
Short copy: /llms.txt.
client_id, open the authorize URL. The person signs in and picks the project. You swap the code for a token.GET /api/v1/me. You get the project, the labels you may use, and the six statuses.curl https://verysimpleprojects.com/api/v1/me \ -H "Authorization: Bearer TOKEN"
Bearer token, scoped to one project. The person revokes it in that project's settings. Tokens do not expire on their own.
Authorization: Bearer TOKEN
Reads always work. New tickets, comments, and title/body edits need an
active subscription (402 otherwise). Status, star, and labels
still work if the plan has lapsed, so a ticket can always be closed.
blocked needs a note that is a concrete ask.done when the work is finished. deployed only when it is actually live, not because you pushed./me lists. Never invent one.
Six, fixed: new, in_progress,
blocked, done, deployed,
cancelled. Open is the first three. Any status may follow
any other. A status change with a note is written into the thread.
GET /meConnect check: the project, your token's name, labels, statuses.
GET https://verysimpleprojects.com/api/v1/me Authorization: Bearer TOKEN
{
"project": { "id": "…", "name": "Agent Heim", "color": "#F2724B" },
"token": { "name": "Agent Heim · Agnes" },
"labels": [{ "id": "…", "name": "bug", "color": "#8A8178" }],
"statuses": ["new", "in_progress", "blocked", "done", "deployed", "cancelled"],
"open": ["new", "in_progress", "blocked"]
}
DELETE /meRevoke this token. Call it before you store a new one on reconnect.
DELETE https://verysimpleprojects.com/api/v1/me Authorization: Bearer TOKEN
{ "ok": true }
GET /labelsLabels the person has made. You cannot add one from here.
GET https://verysimpleprojects.com/api/v1/labels Authorization: Bearer TOKEN
GET /tickets
Query status=open|closed|all|<status> (default
open), optional label=name. Starred first,
then newest activity.
GET https://verysimpleprojects.com/api/v1/tickets?status=open Authorization: Bearer TOKEN
{
"tickets": [
{
"id": "…",
"number": 12,
"title": "Login sheet stays open",
"preview": "First line of the body",
"status": "in_progress",
"important": false,
"labels": [{ "id": "…", "name": "bug", "color": "#8A8178" }],
"commentCount": 3,
"updatedAt": "2026-09-11T12:00:00.000Z",
"closedAt": null
}
]
}
GET /tickets/:numberOne ticket by number, with body and comment thread.
GET https://verysimpleprojects.com/api/v1/tickets/12 Authorization: Bearer TOKEN
POST /tickets
File a ticket. title required. labels is a list
of existing names. Needs an active subscription.
POST https://verysimpleprojects.com/api/v1/tickets
Authorization: Bearer TOKEN
Content-Type: application/json
{ "title": "Login sheet stays open", "body": "## Steps\n1. Tap Continue with Apple", "labels": ["bug"] }
Returns the full ticket with its new number, 201.
PATCH /tickets/:number
Update title, body, status,
note, labels, important.
blocked requires note. Title and body edits
need a subscription; status, star and labels do not.
PATCH https://verysimpleprojects.com/api/v1/tickets/12
Authorization: Bearer TOKEN
Content-Type: application/json
{ "status": "blocked", "note": "Needs a TestFlight build." }
400 bad body, unknown status or label, blocked without a note401 missing or revoked token402 new content without a subscription404 no ticket with that number in this project
The person signs in on verysimpleprojects.com and picks the project. Your
server swaps the code for a project token. Discovery:
/.well-known/oauth-authorization-server.
GET https://verysimpleprojects.com/oauth/authorize
?client_id=…
&redirect_uri=…
&response_type=code
&state=…
&code_challenge=…
&code_challenge_method=S256
POST https://verysimpleprojects.com/oauth/token
grant_type=authorization_code
code=…
redirect_uri=…
client_id=…
client_secret=…
code_verifier=…
→ { "access_token": "…", "token_type": "Bearer" }
PKCE S256 is supported. Clients must be registered by us; email verysimple@portfoliobox.net. Agent Heim is already registered.
Comments
GET /tickets/:number/commentslists the thread, oldest first.POST /tickets/:number/commentswith{ "body" }adds a follow-up. Needs a subscription. APATCHwithnote(and no status change) is the same as posting a comment.POST https://verysimpleprojects.com/api/v1/tickets/12/comments Authorization: Bearer TOKEN Content-Type: application/json { "body": "Reproduced on iOS 26.1." }