Use the REST API
You want a script, a bot or your own tool to work with the forge: open issues, list pull requests, merge, or read CI results.
The REST API is at /api/v1. It speaks JSON and takes a token in the Authorization header. It has the same features as MCP and the src CLI.
1. Make a token
Make a personal access token in Settings, Tokens. For this page, pick Full access, because /user is an account route. Make an access token shows the form. Keep the token in an environment variable:
export TOKEN=<your token>
For an agent, use an agent session token. See Connect your coding agent.
2. Send your first request
curl -H "Authorization: Bearer $TOKEN" https://gitflare.t-zlak97.workers.dev/api/v1/user
The answer is your account, as JSON.
3. Open a pull request
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"title": "Count down to zero", "head": "fix-countdown", "body": "It stopped at 1."}' \
https://gitflare.t-zlak97.workers.dev/api/v1/repos/<owner>/<repo>/pulls
The answer is 201, with the number and the htmlUrl of the new pull request. Without base, the pull request goes into the default branch.
Done
Your script talks to the forge. The same token works for git over HTTPS, MCP and src.
src api sends a request with your src login, so you do not need curl:
src api repos/<owner>/<repo>/pulls
The main routes
| You want to | Route |
|---|---|
| List or open issues | GET or POST /repos/{owner}/{repo}/issues |
| List or open pull requests | GET or POST /repos/{owner}/{repo}/pulls |
| Comment | POST /repos/{owner}/{repo}/issues/{n}/comments |
| Assign people, each with an optional note | POST or PUT /repos/{owner}/{repo}/issues/{n}/assignees |
| Merge | PUT /repos/{owner}/{repo}/pulls/{n}/merge |
| Make a repository | POST /repos |
| Upload an asset | PUT /repos/{owner}/{repo}/assets/files/{path} |
| Change your profile or an organization's | PATCH /user or PATCH /orgs/{org} |
| Upload an image | PUT /user/avatar or PUT /orgs/{org}/avatar |
/llms.txt lists every route, with its fields.
Issue and pull request routes
A path that starts with ... is under /repos/{owner}/{repo}. Issues and pull requests share their numbers.
| You want to | Route | Who can |
|---|---|---|
| Lock or unlock a conversation | PUT or DELETE .../issues/{n}/lock | People with write access |
| Pin or unpin an issue | PUT or DELETE .../issues/{n}/pin | People with write access |
| Move an issue to another repository of the owner | POST .../issues/{n}/transfer | People with write access to both |
| List the branches of an issue, or make one | GET or POST .../issues/{n}/branches | Readers list them, people with write access make one |
| Delete an issue | DELETE .../issues/{n} | Repository admins |
| Mark a draft ready, or make it a draft again | PUT or DELETE .../pulls/{n}/ready | The author, people with write access |
| Ask for reviews, or stop asking | POST .../pulls/{n}/reviewers | The triage role or more |
| Bring the base branch into the head branch | POST .../pulls/{n}/update-branch | People with write access to the head branch |
| Revert a merged pull request | POST .../pulls/{n}/revert | People with write access |
- Lock: the body is
{"reason": "too_heated"}, or empty for no reason. A reason isoff_topic,too_heated,resolvedorspam. - Drafts and reviewers:
POST .../pullsalso takes"draft": trueand"reviewers": ["ana"]. Nobody can merge a draft. - Transfer: the body is
{"repo": "acme/docs"}. After the move,GET .../issues/{n}at the old place answers301with the new place. - Update branch:
{"rebase": true}rebases in place of a merge. Withsha, a head that moved is refused. A conflict gets409. - See Lock, pin, move and delete issues and Drafts, reviews and updates of pull requests.
Repository routes
A path that starts with ... is under /repos/{owner}/{repo}.
| You want to | Route | Who can |
|---|---|---|
| Change the description or the default branch | PATCH /repos/{owner}/{repo} | The maintain role or more |
| Rename a repository | POST .../rename | Repository admins |
| Archive or unarchive a repository | PUT or DELETE .../archive | Repository admins |
| Delete a repository | DELETE /repos/{owner}/{repo} | Repository admins, people only |
| Sync a fork from its parent | POST .../sync | People with write access to the fork, people only |
| List, add or delete autolinks | GET or POST .../autolinks, GET or DELETE .../autolinks/{id} | Repository admins |
| List the templates for a new repository | GET /gitignore/templates, GET /licenses | Everyone |
- Archived: every write to an archived repository gets
403, except the settings of its admins. - Delete: a repository with forks gets
422. Delete the forks first. - New repository:
POST /repostakesgitignore(a template name) andlicense(a license key). Its first commit has the files. - See Rename, archive or delete a repository.
Search routes
A path that starts with ... is under /repos/{owner}/{repo}.
| You want to | Route |
|---|---|
| Filter the issues or the pull requests of a repository | GET .../issues or GET .../pulls, with author=, assignee=, mention= and label= |
| Search issues and pull requests across repositories | GET /search/issues?q= |
| List your issues and pull requests across repositories | GET /user/items?role=assigned, author, review-requested or mentioned |
| Find repositories | GET /search/repos?q= |
| List your organizations | GET /user/orgs |
- A person filter takes a username, or
@mefor you. GET .../pullsalso takeshead=,draft=trueorfalse, andreviewRequested=.GET /search/issuestakeskind=issueorpull,label=,draft=,author=,assignee=,mention=andreviewRequested=.GET /search/reposgives only the repositories that you can read. It leaves out forks unless you addincludeForks=include.
CI routes
The CI reference lists every CI route. These paths are under /repos/{owner}/{repo}:
| You want to | Route | Who can |
|---|---|---|
| Read or change the CI variables | GET /ci/variables, GET, PUT or DELETE /ci/variables/{name} | People with write access read them, admins change them |
| List the workflows, or turn one on or off | GET /ci/workflows, PUT or DELETE /ci/workflows/{workflow}/enabled | Readers list them, admins turn them on or off |
| Delete a run that ended | DELETE /ci/runs/{id} | Repository admins. A run of a pull request gets 422. |
| List the agent jobs | GET /jobs?kind=agent | Everyone who can read the jobs |
Ask the person for a token
Your tool needs a token, and you do not want the person to copy one by hand. Ask for it with the device login. The person checks the request in the browser and creates the token, and your tool gets it.
Start the request. It needs no token:
curl -X POST -H "Content-Type: application/json" \ -d '{"client_name": "my-tool", "token": {"name": "my-tool", "repos": ["acme/app"], "actions": ["contents:read", "pulls:read", "pulls:create"], "ttl": 7200}}' \ https://gitflare.t-zlak97.workers.dev/api/v1/login/device/codeThe answer:
{ "device_code": "<secret>", "user_code": "BCDF-GHJK", "verification_uri": "https://gitflare.t-zlak97.workers.dev/login/device", "verification_uri_complete": "https://gitflare.t-zlak97.workers.dev/settings/tokens/new?code=BCDF-GHJK", "expires_in": 900, "interval": 5 }Show the person
verification_uri_complete. They can change the token there, then click Create token or Deny.Every
intervalseconds, poll with thedevice_code:curl -X POST -H "Content-Type: application/json" \ -d '{"device_code": "<secret>"}' \ https://gitflare.t-zlak97.workers.dev/api/v1/login/device/tokenRead the answer of the poll:
200with{"access_token": "tsp_...", "token_type": "bearer"}: the token. Only the first poll after the approval gets it.400withauthorization_pending: the person did not answer yet. Poll again.400withslow_down: you poll too fast. Wait 5 seconds more between polls.400withaccess_deniedorexpired_token: the person clicked Deny, or 15 minutes passed. Start again.
The fields of token:
name: the name of the token in the person's list.repos: the repositories, asowner/name. At most 20.actions: the actions, for examplecontents:writeorvault:read. The Advanced part of the token form lists them all.ttl: how long the token lives, in seconds. The default is3600, and the most is 365 days.
Your tool gets the token that the person created. It can differ from your request, because the person can change the repositories, the actions and the end time.
Factory and ban routes
These routes run the software factory and bans. A path that starts with ... is under /repos/{owner}/{repo}, or under /orgs/{org} for an organization.
| You want to | Route | Who can |
|---|---|---|
| Read or change the factory settings | GET or PUT .../factory/settings | Repository admins, organization owners |
| List the model keys | GET .../factory/keys | Repository admins, organization owners |
| Save or delete a model key | PUT or DELETE .../factory/keys/{provider} | Repository admins, organization owners |
| List the custom agents | GET /repos/{owner}/{repo}/factory/agents | Repository admins |
| See the custom agents that loaded, and the errors of the files | GET /repos/{owner}/{repo}/factory/agents/status | Repository admins |
| Save or delete a custom agent | PUT or DELETE /repos/{owner}/{repo}/factory/agents/{name} | Repository admins |
| List the runs on an issue or a pull request | GET /repos/{owner}/{repo}/issues/{n}/factory | Everyone who can read the item |
List the repository's newest runs of every item and of the default branch, each with its number (null for the branch); ?limit= up to 500, 50 by default | GET /repos/{owner}/{repo}/factory/runs | People with write access |
| Read one run, its verdicts and its log | GET /repos/{owner}/{repo}/factory/runs/{id} | People with write access |
| Read the architecture of the repository | GET /repos/{owner}/{repo}/architecture | Everyone who can read the code |
| Make the architecture now | POST /repos/{owner}/{repo}/architecture | People with write access |
| Read the impact of a pull request | GET /repos/{owner}/{repo}/pulls/{n}/impact | Everyone who can read the pull request |
| List the bans | GET .../bans | Repository admins, organization owners |
| Ban an account, or lift its ban | PUT or DELETE .../bans/{username} | Repository admins, organization owners |
| Read the spam signals of an account | GET /repos/{owner}/{repo}/bans/{username}/signals | Repository admins |
| List the suggested bans | GET .../bans/suggestions | Repository admins, organization owners |
| Ban the account of a suggested ban, or dismiss it | POST .../bans/suggestions/{id}/accept or .../dismiss | Repository admins, organization owners |
- Settings: a
PUTtakes only the fields that you change. The security audit (audit),architectureandimpactare on by default. Every other agent is off by default. For example,{"agents": {"value": {"enabled": true}}}turns the value check on.nullclears a field, so the organization value or the default holds again. - Architecture:
GET .../architecturegivesrecord(the overview, the packages and the diagrams, ornullbefore the first run), thecommitthat it describes,at,runId,running,enabledandcanGenerate.POSTstarts a run on the tip of the default branch:201with{"runId": "..."}, or200with{"skipped": "<why>"}. See Read the architecture of a repository. - Impact:
GET .../pulls/{n}/impactgives the head commit (headOid), theassessmentof that head, therecord(architectureandpublicApi, each only when it applies),runningandenabled. See Read the Impact tab. - Keys:
PUT .../factory/keys/{provider}takes{"key": "<key>"}. No route gives a key back.GETlists the providers and the time that each key was set. - Custom agents: a
PUTtakes{"script": "<file>"}, a TypeScript file that default-exportsdefineFactory(...). Each agent is{ agent: defineAgent(...), on, trigger, budget }. See Custom agents. - Custom agent status:
GET .../factory/agents/statusgivessource(vaultorrepo-file), theagentsthat loaded (name, factory, file and events), anderrors, one line for each error with its file. It can take a few seconds when the files changed. - Suggested bans:
GET .../bans/suggestionsgives the open ones, each with itsid, the account, the item that the spam agent closed (repoandnumber), thereasonsand thesignals. Add?status=bannedor?status=dismissedfor the decided ones.acceptbans the account with the reason spam. Afterdismiss, the spam agent suggests the same ban again only after 30 days, or with hard proof. - Run logs come one page at a time. Pass
nextfrom the log back as?cursor=. - People only: settings, keys, custom agents and bans refuse an agent session token.
- Appeals: a banned person appeals on the web only. No route opens or decides an appeal.
Skill routes
Find and read skills (no token needed for public skills):
| You want to | Route |
|---|---|
| Search the marketplace | GET /skills?q= |
| List the skills of an owner | GET /skills?owner= |
| List trending, popular skills or tags | GET /skills/trending, GET /skills/popular, GET /skills/tags |
| Read a skill with its files | GET /skills/{address} |
| List the versions, or compare two | GET /skills/versions?address=, GET /skills/diff?address=&from=&to= |
Change your own skills (people only):
| You want to | Route |
|---|---|
| Create a skill | POST /skills |
| Change its files | PATCH /skills/{owner}/{name}/files |
| Rename it, or change its visibility | POST /skills/{owner}/{name}/rename, PUT /skills/{owner}/{name}/visibility |
| Make, list or revoke share links | POST /skills/{owner}/{name}/shares, GET /skills/shares?address=, DELETE /skills/{owner}/{name}/shares/{id} |
| Delete it | DELETE /skills/{owner}/{name} |
Skills in a repository:
| You want to | Route |
|---|---|
| List them, with their state | GET /repos/{owner}/{repo}/skills |
| Add one | POST /repos/{owner}/{repo}/skills |
| Update or remove one | PATCH or DELETE /repos/{owner}/{repo}/skills/{name} |
| Get suggestions | GET /repos/{owner}/{repo}/skills/suggestions |
| Count an install that you made yourself | POST /skills/installs |
A share link of a private skill goes in ?share= or in a share field, never in the Authorization header. See Agent skills for the addresses.
How the API answers
- Errors come back as
{ "error": "<text>" }with the HTTP status. - Lists come back as
{ "items": [...], "next": "<cursor>" }, 100 at a time, newest first. Passnextback as?cursor=, with the same filters, for the next page. - Refused tokens: a token that is unknown, revoked or expired gets
401. It is never treated as anonymous. - Tokens limited to repositories get
403on other repositories and on account routes, such as/user. - Merges take
sha, theheadShathat you read fromGET /pulls/{n}. If the head moved since, the merge is refused with409. - Limits: a title is at most 256 characters, and a body or a comment at most 65,536. A longer one gets
422.