Authentication
shithub's API is PAT-only. There is no OAuth / device-flow / JWT issuance endpoint today.
Header
Authorization: Bearer shp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Authorization: token shp_… is accepted as a synonym for tools
that hard-code GitHub's older syntax.
Token format
PATs are 40 characters of base32 with the shp_ prefix. They
match the regex:
shp_[A-Za-z0-9]{40}
Secret-scanning tools (GitHub's, GitGuardian's, etc.) recognize this prefix.
Failure modes
| Status | Body | Cause |
|---|---|---|
| 401 | {"error":"unauthenticated"} |
Missing or malformed header. |
| 401 | {"error":"invalid token"} |
Token doesn't exist, was revoked, or has expired. |
| 401 | {"error":"account suspended"} |
The owning account has been suspended by an admin. |
| 403 | {"error":"insufficient scope"} |
Token is valid but lacks the scope this route needs. |
Sessions
The web UI uses session cookies, not PATs. Session cookies are
not accepted on /api/v1/ — the API is PAT-only. This is a
deliberate choice: it keeps CSRF concerns off the API surface
and means every API caller is identified by an auditable token.
Creating a token programmatically
There is no API for creating PATs; tokens are only created from the web UI. This is intentional — the create-PAT surface is the account's most security-sensitive non-password operation.
Future
OAuth-style application authorizations (client_id + client_ secret, code exchange, refresh tokens) are planned post-MVP.
For now, instruct human users to mint a PAT from their settings
and supply it to your app via the operator's secret-management
flow.
View source
| 1 | # Authentication |
| 2 | |
| 3 | shithub's API is PAT-only. There is no OAuth / device-flow / JWT |
| 4 | issuance endpoint today. |
| 5 | |
| 6 | ## Header |
| 7 | |
| 8 | ``` |
| 9 | Authorization: Bearer shp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
| 10 | ``` |
| 11 | |
| 12 | `Authorization: token shp_…` is accepted as a synonym for tools |
| 13 | that hard-code GitHub's older syntax. |
| 14 | |
| 15 | ## Token format |
| 16 | |
| 17 | PATs are 40 characters of base32 with the `shp_` prefix. They |
| 18 | match the regex: |
| 19 | |
| 20 | ``` |
| 21 | shp_[A-Za-z0-9]{40} |
| 22 | ``` |
| 23 | |
| 24 | Secret-scanning tools (GitHub's, GitGuardian's, etc.) recognize |
| 25 | this prefix. |
| 26 | |
| 27 | ## Failure modes |
| 28 | |
| 29 | | Status | Body | Cause | |
| 30 | |-------:|-----------------------------------|------------------------------------------------------| |
| 31 | | 401 | `{"error":"unauthenticated"}` | Missing or malformed header. | |
| 32 | | 401 | `{"error":"invalid token"}` | Token doesn't exist, was revoked, or has expired. | |
| 33 | | 401 | `{"error":"account suspended"}` | The owning account has been suspended by an admin. | |
| 34 | | 403 | `{"error":"insufficient scope"}` | Token is valid but lacks the scope this route needs. | |
| 35 | |
| 36 | ## Sessions |
| 37 | |
| 38 | The web UI uses session cookies, not PATs. Session cookies are |
| 39 | **not accepted** on `/api/v1/` — the API is PAT-only. This is a |
| 40 | deliberate choice: it keeps CSRF concerns off the API surface |
| 41 | and means every API caller is identified by an auditable token. |
| 42 | |
| 43 | ## Creating a token programmatically |
| 44 | |
| 45 | There is no API for creating PATs; tokens are only created from |
| 46 | the web UI. This is intentional — the create-PAT surface is the |
| 47 | account's most security-sensitive non-password operation. |
| 48 | |
| 49 | ## Future |
| 50 | |
| 51 | OAuth-style application authorizations (`client_id` + `client_ |
| 52 | secret`, `code` exchange, refresh tokens) are planned post-MVP. |
| 53 | For now, instruct human users to mint a PAT from their settings |
| 54 | and supply it to your app via the operator's secret-management |
| 55 | flow. |