tenseleyflow/shithub / 89bf8df

Browse files

docs/api: issues + labels reference pages

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
89bf8dfa2b8b676814afd99f8ccc3d4df3d86e60
Parents
31f27b2
Tree
111d54d

3 changed files

StatusFile+-
M docs/public/SUMMARY.md 1 0
M docs/public/api/issues.md 178 25
A docs/public/api/labels.md 78 0
docs/public/SUMMARY.mdmodified
@@ -27,6 +27,7 @@
2727
 - [Users](./api/users.md)
2828
 - [Repositories](./api/repos.md)
2929
 - [Issues](./api/issues.md)
30
+- [Labels](./api/labels.md)
3031
 - [Pull requests](./api/pulls.md)
3132
 - [Status checks](./api/checks.md)
3233
 - [Actions workflow API](./api/actions.md)
docs/public/api/issues.mdmodified
@@ -1,27 +1,180 @@
11
 # Issues
22
 
3
-> **Planned.** Issues over the API are not yet shipped. The web
4
-> UI is the only authoring surface today.
5
-
6
-## Planned routes
7
-
8
-| Method | Path                                                   | Scope        |
9
-|--------|--------------------------------------------------------|--------------|
10
-| GET    | `/api/v1/repos/{owner}/{repo}/issues`                  | `repo:read`  |
11
-| GET    | `/api/v1/repos/{owner}/{repo}/issues/{number}`         | `repo:read`  |
12
-| POST   | `/api/v1/repos/{owner}/{repo}/issues`                  | `repo`       |
13
-| PATCH  | `/api/v1/repos/{owner}/{repo}/issues/{number}`         | `repo`       |
14
-| GET    | `/api/v1/repos/{owner}/{repo}/issues/{number}/comments`| `repo:read`  |
15
-| POST   | `/api/v1/repos/{owner}/{repo}/issues/{number}/comments`| `repo`       |
16
-| PATCH  | `/api/v1/repos/{owner}/{repo}/issues/comments/{id}`    | `repo`       |
17
-| DELETE | `/api/v1/repos/{owner}/{repo}/issues/comments/{id}`    | `repo`       |
18
-
19
-Filters on the list endpoint will mirror the web filters
20
-(`state`, `author`, `assignee`, `label`, `milestone`, `since`,
21
-`sort`, `direction`).
22
-
23
-## Markdown rendering
24
-
25
-Posted bodies are stored as raw markdown. Rendering happens at
26
-read time, with the same `internal/markdown` pipeline the web UI
27
-uses, so an API consumer sees the same HTML the browser would.
3
+Issues live per repo. They share the `issues` table with pull
4
+requests, but the REST surface here returns issues only (PRs land
5
+in their own section). Markdown bodies are stored raw; the cached
6
+HTML render comes from the same `internal/markdown` pipeline the
7
+web UI uses.
8
+
9
+## Issue shape
10
+
11
+```json
12
+{
13
+  "id": 17,
14
+  "number": 1,
15
+  "title": "first bug",
16
+  "body": "kaboom",
17
+  "state": "open",
18
+  "state_reason": "",
19
+  "locked": false,
20
+  "lock_reason": "",
21
+  "author_id": 42,
22
+  "labels": ["bug"],
23
+  "created_at": "2026-05-12T05:00:00Z",
24
+  "updated_at": "2026-05-12T05:00:00Z"
25
+}
26
+```
27
+
28
+`state` is `"open"` or `"closed"`. `state_reason` is one of
29
+`"completed"`, `"not_planned"`, `"duplicate"`, `"reopened"`, or
30
+empty when no reason has been recorded. `closed_at` is present
31
+only on closed issues.
32
+
33
+## List issues
34
+
35
+```
36
+GET /api/v1/repos/{owner}/{repo}/issues
37
+```
38
+
39
+Required scope: `repo:read`. Paginated; `?per_page=` (≤100) and
40
+`?page=` apply, with the standard `Link:` header.
41
+
42
+Optional `?state=open|closed|all` filter; `state=all` (or omitted)
43
+returns both.
44
+
45
+Pull requests are not included on this endpoint — fetch them via
46
+the pulls surface.
47
+
48
+## Get a single issue
49
+
50
+```
51
+GET /api/v1/repos/{owner}/{repo}/issues/{number}
52
+```
53
+
54
+Required scope: `repo:read`. `404` when the issue doesn't exist,
55
+when the caller can't see the repo, or when `{number}` belongs to
56
+a pull request (use the pulls surface).
57
+
58
+## Create an issue
59
+
60
+```
61
+POST /api/v1/repos/{owner}/{repo}/issues
62
+```
63
+
64
+Required scope: `repo:write`. Policy: `ActionIssueCreate`.
65
+
66
+```json
67
+{ "title": "first bug", "body": "kaboom" }
68
+```
69
+
70
+| Field   | Type   | Notes                                         |
71
+|---------|--------|-----------------------------------------------|
72
+| `title` | string | Required, 1–256 chars.                        |
73
+| `body`  | string | Optional markdown body, ≤65535 chars.         |
74
+
75
+Returns `201` with the issue envelope.
76
+
77
+### Errors
78
+
79
+| Status | When                                              |
80
+|-------:|---------------------------------------------------|
81
+|    401 | PAT missing/invalid.                              |
82
+|    403 | PAT lacks `repo:write` scope or policy denial.    |
83
+|    422 | Empty title, title too long, body too long.       |
84
+
85
+## Update an issue
86
+
87
+```
88
+PATCH /api/v1/repos/{owner}/{repo}/issues/{number}
89
+```
90
+
91
+Required scope: `repo:write`. Only the fields you send are
92
+modified; everything else stays.
93
+
94
+```json
95
+{
96
+  "title": "first bug — root cause found",
97
+  "body": "see comment #3",
98
+  "state": "closed",
99
+  "state_reason": "completed"
100
+}
101
+```
102
+
103
+Permission rules:
104
+
105
+- **Title / body** — the issue author OR a repo collaborator with
106
+  write access. Other callers `403`.
107
+- **State / state_reason** — any caller with `ActionIssueClose`
108
+  on the repo. `state_reason` must be one of `completed`,
109
+  `not_planned`, `duplicate`, `reopened` (or empty).
110
+
111
+Returns the freshly-loaded issue.
112
+
113
+## Lock and unlock
114
+
115
+```
116
+PUT    /api/v1/repos/{owner}/{repo}/issues/{number}/lock
117
+DELETE /api/v1/repos/{owner}/{repo}/issues/{number}/lock
118
+```
119
+
120
+Required scope: `repo:write`. PUT body is optional:
121
+
122
+```json
123
+{ "lock_reason": "off-topic" }
124
+```
125
+
126
+Returns `204`. Locking refuses non-collaborator comments; the
127
+issue itself stays visible.
128
+
129
+## Comments
130
+
131
+### List
132
+
133
+```
134
+GET /api/v1/repos/{owner}/{repo}/issues/{number}/comments
135
+```
136
+
137
+Required scope: `repo:read`. Returns comments in chronological
138
+order.
139
+
140
+### Add
141
+
142
+```
143
+POST /api/v1/repos/{owner}/{repo}/issues/{number}/comments
144
+```
145
+
146
+Required scope: `repo:write`. Policy: `ActionIssueComment`. Body:
147
+
148
+```json
149
+{ "body": "lgtm" }
150
+```
151
+
152
+Subject to the per-author comment rate limit (20/hour); `429`
153
+when exceeded.
154
+
155
+### Edit own comment
156
+
157
+```
158
+PATCH /api/v1/repos/{owner}/{repo}/issues/comments/{cid}
159
+```
160
+
161
+Required scope: `repo:write`. The comment author can edit their
162
+own; other callers `403`.
163
+
164
+### Delete a comment
165
+
166
+```
167
+DELETE /api/v1/repos/{owner}/{repo}/issues/comments/{cid}
168
+```
169
+
170
+Required scope: `repo:write`. The comment author can delete their
171
+own; repo collaborators with write access can delete any comment
172
+on the repo (moderation affordance, matches the gh shape).
173
+
174
+Returns `204`.
175
+
176
+## Not yet shipped
177
+
178
+`POST /api/v1/repos/{o}/{r}/issues/{n}/transfer`, pinning,
179
+applying labels / assignees / milestones over the issue PATCH —
180
+all queued for a follow-up batch.
docs/public/api/labels.mdadded
@@ -0,0 +1,78 @@
1
+# Labels
2
+
3
+Repo-scoped labels for issues and pull requests. The default
4
+label set is seeded at repo create and can be edited or removed
5
+freely.
6
+
7
+## Label shape
8
+
9
+```json
10
+{
11
+  "id": 7,
12
+  "name": "bug",
13
+  "color": "ee0701",
14
+  "description": "Something isn't working",
15
+  "created_at": "2026-05-12T05:00:00Z"
16
+}
17
+```
18
+
19
+`color` is six hex chars without the leading `#`.
20
+
21
+## List labels
22
+
23
+```
24
+GET /api/v1/repos/{owner}/{repo}/labels
25
+```
26
+
27
+Required scope: `repo:read`. Sorted alphabetically by name.
28
+
29
+## Get a single label
30
+
31
+```
32
+GET /api/v1/repos/{owner}/{repo}/labels/{name}
33
+```
34
+
35
+Required scope: `repo:read`. `404` when the label does not exist.
36
+
37
+## Create a label
38
+
39
+```
40
+POST /api/v1/repos/{owner}/{repo}/labels
41
+```
42
+
43
+Required scope: `repo:write`. Policy: `ActionIssueLabel`.
44
+
45
+```json
46
+{ "name": "needs-triage", "color": "ff00aa", "description": "triage me" }
47
+```
48
+
49
+| Field         | Type   | Notes                                  |
50
+|---------------|--------|----------------------------------------|
51
+| `name`        | string | Required, 1–50 chars.                  |
52
+| `color`       | string | Required, six hex chars (no `#`).      |
53
+| `description` | string | Optional, ≤100 chars.                  |
54
+
55
+Returns `201`. `409` when the name is already taken on the repo;
56
+`422` on invalid color or empty name.
57
+
58
+## Update a label
59
+
60
+```
61
+PATCH /api/v1/repos/{owner}/{repo}/labels/{name}
62
+```
63
+
64
+Required scope: `repo:write`. Send only the fields you want to
65
+change. Renaming a label is allowed via `name`.
66
+
67
+```json
68
+{ "color": "00ff00", "description": "ready for triage" }
69
+```
70
+
71
+## Delete a label
72
+
73
+```
74
+DELETE /api/v1/repos/{owner}/{repo}/labels/{name}
75
+```
76
+
77
+Required scope: `repo:write`. Returns `204`. Issue / PR label
78
+associations cascade away automatically.