[WIP] feat: scoped api keys

This commit is contained in:
Iris System 2025-08-17 02:47:01 -07:00
parent e7ee593a85
commit 06cb160f95
45 changed files with 1264 additions and 154 deletions

View file

@ -77,7 +77,8 @@ module.exports = {
"/api/endpoints",
"/api/models",
"/api/errors",
"/api/dispatch"
"/api/tokens",
"/api/dispatch",
]
},
["https://discord.gg/PczBt78", "Join the support server"],

View file

@ -42,7 +42,7 @@ The PluralKit Discord bot can be configured to display short IDs in uppercase, o
|---|---|---|
|id|string||
|uuid|string||
|?system|string|id of system this member is registered in (only returned in `/members/:id` endpoint)|
|system|string|id of system this member is registered in|
|name|string|100-character limit|
|display_name|?string|100-character limit|
|color|?string|6-character hex code, no `#` at the beginning|
@ -78,7 +78,7 @@ The PluralKit Discord bot can be configured to display short IDs in uppercase, o
|---|---|---|
|id|string||
|uuid|string||
|?system|string|id of system this group is registered in (only returned in `/groups/:id` endpoint)|
|system|string|id of system this group is registered in|
|name|string|100-character limit|
|display_name|?string|100-character limit|
|description|?string|1000-character limit|
@ -96,7 +96,7 @@ The PluralKit Discord bot can be configured to display short IDs in uppercase, o
|---|---|---|
|id|uuid||
|timestamp|datetime||
| members | list of id/Member | Is sometimes in plain ID list form (eg. `GET /systems/:id/switches`), sometimes includes the full Member model (eg. `GET /systems/:id/fronters`). |
|members|list of id/Member|Is sometimes in plain ID list form (eg. `GET /systems/:id/switches`), sometimes includes the full Member model (eg. `GET /systems/:id/fronters`)|
### Message model
@ -121,6 +121,13 @@ The PluralKit Discord bot can be configured to display short IDs in uppercase, o
|member_default_private*|boolean|whether members created through the bot have privacy settings set to private by default|
|group_default_private*|boolean|whether groups created through the bot have privacy settings set to private by default|
|show_private_info|boolean|whether the bot shows the system's own private information without a `-private` flag|
|case_sensitive_proxy_tags|boolean|whether the system's member proxy tags are parsed as case sensitive|
|proxy_error_message_enabled|boolean|whether to show proxying-specific error messages|
|hid_display_split|boolean|if enabled, the system prefers 6-character IDs to be displayed with a hyphen splitting each group of 3 characters|
|hid_display_caps|boolean|if enabled, the system prefers short IDs to be displayed in all-caps|
|hid_list_padding|one of "off", "left", "right"|system preference for padding short IDs in lists|
|proxy_switch|one of "off", "new", "add"||
|name_format|string|formatting template for display names for the system's proxied messages|
|member_limit|int|read-only, defaults to 1000|
|group_limit|int|read-only, defaults to 250|
|case_sensitive_proxy_tags|bool|whether the bot will match proxy tags matching only the case used in the trigger message|

View file

@ -8,11 +8,6 @@ permalink: /api
PluralKit has a basic HTTP REST API for querying and modifying your system.
The root endpoint of the API is `https://api.pluralkit.me/v2/`.
#### Authorization header token example
```
Authorization: z865MC7JNhLtZuSq1NXQYVe+FgZJHBfeBCXOPYYRwH4liDCDrsd7zdOuR45mX257
```
Endpoints will always return all fields, using `null` when a value is missing. On `PATCH` endpoints,
missing fields from the JSON request will be ignored and preserved as is, but on `POST` endpoints will
be set to `null` or cleared.
@ -29,14 +24,12 @@ If you are developing an application exposed to the public, we would appreciate
## Authentication
Authentication is done with a simple "system token". You can get your system token by running `pk;token` using the
Discord bot, either in a channel with the bot or in DMs. Then, pass this token in the `Authorization` HTTP header
on requests that require it. Failure to do so on endpoints that require authentication will return a `401 Unauthorized`.
Authentication is done with an API key provided in the `Authorization` HTTP header - [see the API key section of the documentation for details.](/api/tokens)
Some endpoints show information that a given system may have set to private. If this is a specific field
(eg. description), the field will simply contain `null` rather than the true value. If this applies to entire endpoint
responses (eg. fronter, switches, member list), the entire request will return `403 Forbidden`. Authenticating with the
system's token (as described above) will override these privacy settings and show the full information.
Some endpoints show information that a given system may have set to private. For unauthenticated requests, and for requests authenticated with an API key that does not have permission to read private data, the following rules apply:
- For fields with specific privacy settings (e.g. descriptions), the field will simply contain `null` rather than the true value
- For entire endpoints which show private data (e.g. member/group lists), a `403 Forbidden` response will be returned
## Rate Limiting
@ -46,7 +39,7 @@ To protect against abuse and manage server resources, PluralKit's API limits the
- **10/second** for requests to the [Get Proxied Message Information](/api/endpoints/#get-proxied-message-information) endpoint (`message` scope)
- **3/second** for any `POST`, `PATCH`, or `DELETE` requests (`generic_update` scope)
We may raise the limits for individual users in a case-by-case basis; please ask [in the support server](https://discord.gg/PczBt78) if you need a higher limit.
We may raise the limits for individual API clients on a case-by-case basis; please ask [in the support server](https://discord.gg/PczBt78) if you need a higher limit.
::: tip
If you are looking to query a specific resource in your system repeatedly (polling), please consider using [Dispatch Webhooks](/api/dispatch) instead.

View file

@ -0,0 +1,79 @@
---
title: API keys / tokens
permalink: /api/tokens
---
# API keys / tokens
There are currently two types of API keys / tokens used by PluralKit - "legacy" tokens from the `pk;token` command (64 characters, a system can only have one valid token at a time); and "modern" API keys (variable length, always start with `pkapi:').
## "Legacy" tokens
"Legacy" PluralKit tokens look similar to the following:
```
LvWacQm3Yu+Jbhl8B7LR97Q4kfpAasTiB8/BY5/HJCppHFggzwOai6QBxehAJ53C
```
These tokens are supplied *as-is* in the `Authorization` HTTP header when talking to the PluralKit API (e.g. `Authorization: LvWacQm3Y...`)
Each PluralKit system can only have *one* valid "legacy" token at a time, and that token holds the keys to the entire castle - it grants full read/write privileges.
**PluralKit's API will stop accepting "legacy" tokens for authentication in the near future!** We do not yet have a deprecation plan set in stone, but there will be a significant notice period before this happens.
## "Modern" API keys
A "modern" PluralKit API key is made up of three components, separated by colons:
- The string `"pkapi"`
- A Base64-encoded JSON blob containing information about the API key
- An opaque signature
As an example:
```
pkapi:eyJ0aWQiOiI3NWEzODZlNy1mMjNlLTRmM2EtYjkwNC1jYTgwMzE0OWFmNWEiLCJzaWQiOiIyMmIwYjA3Yi00ZmE3LTRmYTEtYmYyNS1lZWI4NjY1ZjMyYzEiLCJ0eXBlIjoidXNlcl9jcmVhdGVkIiwic2NvcGVzIjpbIndyaXRlOmFsbCJdfQ==:nUjJPPtBOyPb1bYFhm24bU87N2Fb_oSaNnHEZkB-6ZSCSlAJvkyb32MTfmdEv3U6wNBlBQtQb0Fkv2nSvbNsCw
```
These tokens must be supplied with a "Bearer" prefix in the `Authorization` HTTP header when talking to the PluralKit API (e.g. `Authorization: Bearer pkapi:eyJ0aW...`).
The JSON blob in the above example API key contains the following:
```js
{
// API key ID
"tid": "75a386e7-f23e-4f3a-b904-ca803149af5a",
// UUID of the PluralKit system the token belongs to
"sid": "22b0b07b-4fa7-4fa1-bf25-eeb8665f32c1",
// "user_created" for manually generated API keys,
// "external_app" for OAuth2 user API keys (coming soon!)
"type": "user_created",
// One or more scopes (see below)
"scopes": ["write:all"]
}
```
### Scopes
In the below table, `<X>` refers to a *permission level* - one of the following:
- `publicread`: read-only access to *public* information
- `read`: read-only access to all (public *and* private) information
- `write`: read-write access to all information (implies `read`)
|scope|notes|
|---|---|
|`identify`|Read-only access to `/v2/systems/@me` - for proving the user providing the token has control of the PluralKit system|
|`<X>:system`|Access to core system data, system settings (including autoproxy), and server-specific settings|
|`<X>:members`|Access to member information, *not including group membership*|
|`<X>:groups`|Access to group information|
|`<X>:fronters`|Access to current system fronters|
|`<X>:switches`|Access to full system switch history (implies `<X>:fronters`)|
|`<X>:all`|Includes all other scopes|
### Issuing new API keys
TODO