Users
Get the authenticated user
GET /api/v1/user
Required scope: user:read.
Returns the user record for the account that owns the authenticating PAT.
Response
{
"id": 42,
"username": "alice",
"name": "Alice Example",
"email_verified": true,
"created_at": "2026-05-09T16:30:00Z"
}
| Field | Type | Notes |
|---|---|---|
id |
int64 | Stable numeric ID. |
username |
string | Account username; URL-safe slug. |
name |
string | Display name; may be empty if not set. |
email_verified |
bool | Whether the primary email has been verified. |
created_at |
string | RFC 3339 UTC timestamp of account creation. |
Errors
| Status | When |
|---|---|
| 401 | PAT missing/invalid/expired/revoked. |
| 403 | PAT lacks user:read scope. |
| 404 | User record not found (suspended or deleted between auth and lookup). |
Get a user by username
Planned.
GET /api/v1/users/{username}is not shipped yet.
Update the authenticated user
Planned.
PATCH /api/v1/useris not shipped yet.
List the authenticated user's repos
Planned.
GET /api/v1/user/reposis not shipped yet.
Email addresses
List the authenticated user's emails
GET /api/v1/user/emails
Required scope: user:read.
Returns every email address attached to the authenticating user.
Use ?verified=true (or ?verified=false) to filter to a single
verification state. Omit the query parameter to list both.
Response
[
{
"id": 7,
"email": "alice+primary@example.test",
"primary": true,
"verified": true
},
{
"id": 8,
"email": "alice+work@example.test",
"primary": false,
"verified": false
}
]
| Field | Type | Notes |
|---|---|---|
id |
int64 | Stable per-row id. |
email |
string | The email address as stored. |
primary |
bool | Marks the account's primary delivery address. |
verified |
bool | true once a verification link has been clicked. |
Errors
| Status | When |
|---|---|
| 401 | PAT missing/invalid/expired/revoked. |
| 403 | PAT lacks user:read scope. |
Planned.
POSTandDELETE /api/v1/user/emailsare not shipped yet — use/settings/accountin the web UI to add or remove addresses for now.
SSH keys
SSH authentication keys for git-over-SSH. Signing keys live at a
separate /user/ssh_signing_keys surface (not yet shipped).
List SSH keys
GET /api/v1/user/keys
Required scope: user:read.
Returns the authenticated user's authentication keys (signing
keys are not returned here). Paginated via ?per_page= and
?page=; the response carries the standard Link: header.
Response
[
{
"id": 12,
"title": "laptop",
"key": "ssh-ed25519 AAAA…",
"fingerprint": "SHA256:abc…",
"key_type": "ssh-ed25519",
"verified": true,
"read_only": false,
"created_at": "2026-05-12T04:00:00Z"
}
]
Get a single SSH key
GET /api/v1/user/keys/{id}
Required scope: user:read.
404 when the id does not belong to the authenticating user, or when it is a signing key (use the signing-key surface).
Add an SSH key
POST /api/v1/user/keys
Required scope: user:write.
Request body
{ "title": "laptop", "key": "ssh-ed25519 AAAA…" }
| Field | Type | Notes |
|---|---|---|
title |
string | 1–80 characters; user-visible label. |
key |
string | The contents of your .pub file (no leading comment, no trailing data). |
Returns 201 on success with the same shape as the list endpoint.
Errors
| Status | When |
|---|---|
| 401 | PAT missing/invalid. |
| 403 | PAT lacks user:write scope. |
| 422 | Title invalid, blob unparseable, key already registered, or per-user cap hit. |
Delete an SSH key
DELETE /api/v1/user/keys/{id}
Required scope: user:write.
Returns 204 No Content on success, 404 when the id does not
belong to the authenticating user.
Stars
The starred-repos surface for the authenticating user.
List starred repos
GET /api/v1/user/starred
Required scope: user:read.
Returns the list of (owner, repo) pairs the user has starred,
most-recent first. Pagination via ?cursor=… and ?per_page=.
Star a repo
PUT /api/v1/user/starred/{owner}/{repo}
Required scope: user (write).
Idempotent: starring an already-starred repo returns 204 and
does not duplicate the row. Returns 404 if the repo doesn't
exist or the user can't see it.
Unstar a repo
DELETE /api/v1/user/starred/{owner}/{repo}
Required scope: user (write).
Idempotent: unstarring a not-starred repo returns 204.
View source
| 1 | # Users |
| 2 | |
| 3 | ## Get the authenticated user |
| 4 | |
| 5 | ``` |
| 6 | GET /api/v1/user |
| 7 | ``` |
| 8 | |
| 9 | Required scope: `user:read`. |
| 10 | |
| 11 | Returns the user record for the account that owns the |
| 12 | authenticating PAT. |
| 13 | |
| 14 | ### Response |
| 15 | |
| 16 | ```json |
| 17 | { |
| 18 | "id": 42, |
| 19 | "username": "alice", |
| 20 | "name": "Alice Example", |
| 21 | "email_verified": true, |
| 22 | "created_at": "2026-05-09T16:30:00Z" |
| 23 | } |
| 24 | ``` |
| 25 | |
| 26 | | Field | Type | Notes | |
| 27 | |------------------|---------|------------------------------------------------------| |
| 28 | | `id` | int64 | Stable numeric ID. | |
| 29 | | `username` | string | Account username; URL-safe slug. | |
| 30 | | `name` | string | Display name; may be empty if not set. | |
| 31 | | `email_verified` | bool | Whether the primary email has been verified. | |
| 32 | | `created_at` | string | RFC 3339 UTC timestamp of account creation. | |
| 33 | |
| 34 | ### Errors |
| 35 | |
| 36 | | Status | When | |
| 37 | |-------:|-------------------------------------| |
| 38 | | 401 | PAT missing/invalid/expired/revoked. | |
| 39 | | 403 | PAT lacks `user:read` scope. | |
| 40 | | 404 | User record not found (suspended or deleted between auth and lookup). | |
| 41 | |
| 42 | ## Get a user by username |
| 43 | |
| 44 | > **Planned.** `GET /api/v1/users/{username}` is not shipped yet. |
| 45 | |
| 46 | ## Update the authenticated user |
| 47 | |
| 48 | > **Planned.** `PATCH /api/v1/user` is not shipped yet. |
| 49 | |
| 50 | ## List the authenticated user's repos |
| 51 | |
| 52 | > **Planned.** `GET /api/v1/user/repos` is not shipped yet. |
| 53 | |
| 54 | ## Email addresses |
| 55 | |
| 56 | ### List the authenticated user's emails |
| 57 | |
| 58 | ``` |
| 59 | GET /api/v1/user/emails |
| 60 | ``` |
| 61 | |
| 62 | Required scope: `user:read`. |
| 63 | |
| 64 | Returns every email address attached to the authenticating user. |
| 65 | Use `?verified=true` (or `?verified=false`) to filter to a single |
| 66 | verification state. Omit the query parameter to list both. |
| 67 | |
| 68 | #### Response |
| 69 | |
| 70 | ```json |
| 71 | [ |
| 72 | { |
| 73 | "id": 7, |
| 74 | "email": "alice+primary@example.test", |
| 75 | "primary": true, |
| 76 | "verified": true |
| 77 | }, |
| 78 | { |
| 79 | "id": 8, |
| 80 | "email": "alice+work@example.test", |
| 81 | "primary": false, |
| 82 | "verified": false |
| 83 | } |
| 84 | ] |
| 85 | ``` |
| 86 | |
| 87 | | Field | Type | Notes | |
| 88 | |------------|--------|---------------------------------------------------| |
| 89 | | `id` | int64 | Stable per-row id. | |
| 90 | | `email` | string | The email address as stored. | |
| 91 | | `primary` | bool | Marks the account's primary delivery address. | |
| 92 | | `verified` | bool | `true` once a verification link has been clicked. | |
| 93 | |
| 94 | #### Errors |
| 95 | |
| 96 | | Status | When | |
| 97 | |-------:|-------------------------------------| |
| 98 | | 401 | PAT missing/invalid/expired/revoked. | |
| 99 | | 403 | PAT lacks `user:read` scope. | |
| 100 | |
| 101 | > **Planned.** `POST` and `DELETE /api/v1/user/emails` are not |
| 102 | > shipped yet — use `/settings/account` in the web UI to add or |
| 103 | > remove addresses for now. |
| 104 | |
| 105 | ## SSH keys |
| 106 | |
| 107 | SSH authentication keys for git-over-SSH. Signing keys live at a |
| 108 | separate `/user/ssh_signing_keys` surface (not yet shipped). |
| 109 | |
| 110 | ### List SSH keys |
| 111 | |
| 112 | ``` |
| 113 | GET /api/v1/user/keys |
| 114 | ``` |
| 115 | |
| 116 | Required scope: `user:read`. |
| 117 | |
| 118 | Returns the authenticated user's authentication keys (signing |
| 119 | keys are not returned here). Paginated via `?per_page=` and |
| 120 | `?page=`; the response carries the standard `Link:` header. |
| 121 | |
| 122 | #### Response |
| 123 | |
| 124 | ```json |
| 125 | [ |
| 126 | { |
| 127 | "id": 12, |
| 128 | "title": "laptop", |
| 129 | "key": "ssh-ed25519 AAAA…", |
| 130 | "fingerprint": "SHA256:abc…", |
| 131 | "key_type": "ssh-ed25519", |
| 132 | "verified": true, |
| 133 | "read_only": false, |
| 134 | "created_at": "2026-05-12T04:00:00Z" |
| 135 | } |
| 136 | ] |
| 137 | ``` |
| 138 | |
| 139 | ### Get a single SSH key |
| 140 | |
| 141 | ``` |
| 142 | GET /api/v1/user/keys/{id} |
| 143 | ``` |
| 144 | |
| 145 | Required scope: `user:read`. |
| 146 | |
| 147 | 404 when the id does not belong to the authenticating user, or |
| 148 | when it is a signing key (use the signing-key surface). |
| 149 | |
| 150 | ### Add an SSH key |
| 151 | |
| 152 | ``` |
| 153 | POST /api/v1/user/keys |
| 154 | ``` |
| 155 | |
| 156 | Required scope: `user:write`. |
| 157 | |
| 158 | #### Request body |
| 159 | |
| 160 | ```json |
| 161 | { "title": "laptop", "key": "ssh-ed25519 AAAA…" } |
| 162 | ``` |
| 163 | |
| 164 | | Field | Type | Notes | |
| 165 | |---------|--------|--------------------------------------------------------------------------| |
| 166 | | `title` | string | 1–80 characters; user-visible label. | |
| 167 | | `key` | string | The contents of your `.pub` file (no leading comment, no trailing data). | |
| 168 | |
| 169 | Returns `201` on success with the same shape as the list endpoint. |
| 170 | |
| 171 | #### Errors |
| 172 | |
| 173 | | Status | When | |
| 174 | |-------:|------------------------------------------------------------------------------| |
| 175 | | 401 | PAT missing/invalid. | |
| 176 | | 403 | PAT lacks `user:write` scope. | |
| 177 | | 422 | Title invalid, blob unparseable, key already registered, or per-user cap hit. | |
| 178 | |
| 179 | ### Delete an SSH key |
| 180 | |
| 181 | ``` |
| 182 | DELETE /api/v1/user/keys/{id} |
| 183 | ``` |
| 184 | |
| 185 | Required scope: `user:write`. |
| 186 | |
| 187 | Returns `204 No Content` on success, `404` when the id does not |
| 188 | belong to the authenticating user. |
| 189 | |
| 190 | ## Stars |
| 191 | |
| 192 | The starred-repos surface for the authenticating user. |
| 193 | |
| 194 | ### List starred repos |
| 195 | |
| 196 | ``` |
| 197 | GET /api/v1/user/starred |
| 198 | ``` |
| 199 | |
| 200 | Required scope: `user:read`. |
| 201 | |
| 202 | Returns the list of `(owner, repo)` pairs the user has starred, |
| 203 | most-recent first. Pagination via `?cursor=…` and `?per_page=`. |
| 204 | |
| 205 | ### Star a repo |
| 206 | |
| 207 | ``` |
| 208 | PUT /api/v1/user/starred/{owner}/{repo} |
| 209 | ``` |
| 210 | |
| 211 | Required scope: `user` (write). |
| 212 | |
| 213 | Idempotent: starring an already-starred repo returns `204` and |
| 214 | does not duplicate the row. Returns `404` if the repo doesn't |
| 215 | exist or the user can't see it. |
| 216 | |
| 217 | ### Unstar a repo |
| 218 | |
| 219 | ``` |
| 220 | DELETE /api/v1/user/starred/{owner}/{repo} |
| 221 | ``` |
| 222 | |
| 223 | Required scope: `user` (write). |
| 224 | |
| 225 | Idempotent: unstarring a not-starred repo returns `204`. |