Documentation
The API
Every route under /api/v1 is documented as OpenAPI/Swagger — the endpoint list, request and response shapes, and a try-it console live at /api/docs. This page covers the two things Swagger doesn't: how to authenticate, and what actually works today versus what the shape of the API implies should work.
Authentication
There are three supported ways to authenticate. Pick the one that matches the caller.
- Identify a document. Names are unique within an owner's account. Creating a repository returns its immutable
id,name,owner, browserurlandgit_url. Use that ID wherever the API says{repo}. To look up an existing document, useGET /api/v1/repos/{owner}/{name}; the same read permissions apply. Browser addresses use/{owner}/r/{name}, and Git remotes use/{owner}/{name}.git. - Session cookie.
POST /api/v1/loginwith an email and password sets the same session cookie the web UI uses. Every write through this cookie also needs anx-csrf-tokenheader carrying the token that login response returns — a plain cookie is not enough to authorize a write, on purpose. - Hosted connector. A remote MCP client discovers Writ's OAuth server, opens browser consent, and receives short-lived bearer credentials for only the selected documents and abilities. The client refreshes those credentials without asking you to paste a token. See Connect an agent.
- Developer token. Create one under Connected agents, choosing documents and abilities. A local harness authenticates with
Authorization: Bearer <token>. Writ shows the secret once; keep it in an environment or secret store. This path remains separate from hosted OAuth connections.
Bearer requests are authoritative: if a request carries an Authorization header, Writ never falls back to a more powerful browser session cookie. OAuth abilities and document grants apply to the JSON API and MCP alike.
What an agent can do today
Once authenticated, an agent can use the operations allowed by its scopes and document membership:
- Read files, threads, and rules in an explicitly granted document. A hosted connection does not inherit all of its operator's documents, and its grant also limits public documents.
- List, start, read, autosave, rename, and submit its own working edits through
/api/v1/r/{repo}/edits. The browser, REST clients, and hosted agents share this API and its persistentEdit 1,Edit 2numbering. A save keeps the text as a draft and writes no commit; submit turns the draft into exactly one commit on the edit branch. Because nothing is committed in between, theversiona save returns is the same one it was given, and that is the token the next save sends. Every save still carries the exact version and blob from the preceding read, so work against a branch that has moved returns 409 instead of overwriting a newer edit.PATCH /api/v1/r/{repo}/edits/{slug}changes only the friendly label; the underlying Git ref stays stable. - Leave a comment, reply, approve, or close a thread.
- Open a submission for a branch it has already pushed to over Git.
- Resolve a text conflict. When Finish answers 409 because
mainmoved underneath the branch,GET /api/v1/r/{repo}/merges/{number}/conflictslists each overlap with the wording onmain, the wording on the branch, and the common ancestor.POSTto the same path with a choice per overlap —main,branch,both,baseorrewritewith your own text — and the merge lands. You must pass back themain_shathe GET gave you, asbase_main_sha: ifmainmoved while you were deciding, the request is refused rather than overwriting a sentence you never saw.base_blob_shais optional and guards your own branch the same way. - Finish a submission —
POST /api/v1/r/{repo}/merges/{number}/mergereaches the identical code path the web UI's Finish button does. Human-authored meaning changes require no separate approval while the author is the document's only active human; team documents apply their configured quorum. An agent-authored meaning change always needs a different human. - Inspect the applied gate —
GET /api/v1/r/{repo}/threads/{number}includesderivedstate with counted and eligible principal ids, the configured and currently required approval counts, mergeability reasons, andsolo_human_projectwhen that exemption applies. - Configure review policy — repo members can read settings with
GET /api/v1/r/{repo}/settings; the repo owner can partially update policies, squash behavior and LLM settings withPATCH. Setsemantic_approval.allow_self_approvalto let an otherwise eligible human author contribute to the existing quorum.
What an agent cannot do today
- Be told when something happens. An agent can poll a repo's activity with
GET /api/v1/r/{repo}/events, passing the last id it saw assince. There's no push and no stream, so an agent that wants to react promptly has to ask repeatedly.
For the endpoint list, exact parameters, and response shapes, use the interactive reference at /api/docs.