Authentication
The Keystash API makes use of Authorization Bearer Tokens. Bearer authentication (also called token authentication) is an HTTP authentication scheme that involves security tokens called bearer tokens. The name “Bearer authentication” can be understood as “give access to the bearer of this token.” The client must send this token in the Authorization header when making requests to protected resources:
Authorization: Bearer <token>
The Bearer authentication scheme was originally created as part of OAuth 2.0 in RFC 6750, but is sometimes also used on its own. Bearer authentication should only be used over HTTPS (SSL).
Keystash supports two ways to obtain a Bearer token: a Personal Access Token (recommended) or the legacy username and password Login flow (deprecated). Both are presented in the same Authorization: Bearer <token> header, so a Personal Access Token is a drop-in replacement for a login token on every request.
Authentication is carried out against a normal Keystash user account, and the permissions granted in Keystash apply to the API in the same way. Therefore if a user does not have access to Server Groups inside Keystash, then they won't have access to Server Groups via the API. Because a token inherits the full permissions of the user who created it, we suggest you create a Personal Access Token under a separate user account dedicated to your integration. This way your integration only has the access it needs, and it doesn't stop working if a person's individual account is removed.
Info
Single sign-on (SSO) users can use the API with a Personal Access Token. Because a token is created from your Profile page and presented directly, it does not depend on the username and password login flow, so you do not need to create a separate non-SSO user.
Personal Access Tokens
A Personal Access Token is a single, long-lived credential you present as Authorization: Bearer kst_…. There is no login round-trip and no one-hour expiry to work around: a token is valid until its chosen expiry date, or until you revoke it. This makes it the recommended way to authenticate integrations, scripts and AI agents against the Keystash API.
You create a Personal Access Token from your Profile page. Token management is handled entirely in that view, so there is no API endpoint for creating, listing or revoking tokens.
Warning
A Personal Access Token has the same permissions as the user who created it — there is no way to limit a token to a subset of actions. Treat it like a password. We recommend creating each token under a dedicated integration user whose Role grants only the access that integration needs, and creating a separate token per integration so you can revoke one without affecting the others.
Note
Your token is shown only once, at the moment you create it. Keystash stores only a one-way hash of the token, so it cannot be recovered afterwards. If you lose a token, revoke it and create a new one. Store it in a secrets manager, never in source control.
Note
Every Personal Access Token begins with kst_. Only the first few characters are retained so Keystash can help you identify a token in the list; the rest is stored as a one-way hash and cannot be read back.
Authentication: Bearer Token
To authenticate, send your Personal Access Token in the Authorization header on any protected endpoint. The following example lists your Server Groups.
Example Request
curl --location --request GET 'https://app.keystash.io/api/v1/servers/list' \
--header 'Authorization: Bearer kst_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
Example Error Response
If the token is missing, malformed, expired or revoked, the API responds with a 401 Unauthorized and the InvalidPersonalAccessToken code.
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "InvalidPersonalAccessToken",
"message": "Your Personal Access Token is not valid, has expired, or has been revoked. Please create a new one.",
"details": []
}
}
Login
Warning
The username and password Login flow is deprecated and will be removed in January 2027. We recommend switching all integrations to Personal Access Tokens before then.
Path: /login
Method: POST
Request Headers
| Param | Value | Required |
|---|---|---|
Accept-Encoding |
gzip | optional |
Request Body
| Key | Value | Notes |
|---|---|---|
username |
max@example.org | urlencoded |
password |
mySecurePassword | urlencoded |
Note
Use your Keystash username (email address) and password to login.
Example Request
curl --location --request POST 'https://app.keystash.io/api/v1/login' \
--header 'Accept-Encoding: gzip' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'username=max@example.org' \
--data-urlencode 'password=mySecurePassword'
Example Response
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"authenticated": true,
"token": "vyJhbGciOiJIUzI1NiIsInR5cCI6kpXVCJ9.eyJzZXNzaW9uX2lkIjoiSXNwTDNnYlVFeS1QWlFvb2JnWFItYUd1ck9jTXAyLXMiLCJpYXQiOjE2NjQyODY4OTcsImV4cCI6MTY2NDMzMertterNywiYXVkIjoiYXBwLmtleXN0YXNoLmlvIiwiaXNzIjoiYXBwLmtleXN0YqNoLmlvIn0.m2cXsqIjFlxHwW2_Jxz9bgwxxyXrOzpIyGIxyEyAOFg",
"message": "Authentication successful."
}
Example Error Response
HTTP/1.1 403
Content-Type: application/json; charset=utf-8
{
"error":"The authentication credentials were not valid. Please re-authenticate with the correct username and password."
}
Note
The token will need to be supplied with each API request as the authentication token.
The token is valid for 1 hour and you will need to re-authenticate once it has expired.
Permission Error Response
A user's Role determines which paths they can reach, regardless of whether you authenticated with a Personal Access Token or the Login flow. If the authenticated user lacks permission for a path, the API responds with a 403 Forbidden.
HTTP/1.1 403
Content-Type: application/json; charset=utf-8
{
"error": {
"code": "Forbidden",
"message": "You do not have the required permission to access this path.",
"details": [
{
"path": "/api/v1/servers/list"
}
]
}
}