---
title: "Sblurp API: sign-in and tokens"
description: "How sign-in works across Sblurp: OAuth 2.0 with PKCE at sblurp.chat, per-server access tokens, JWT claims, refresh token rotation, JWKS, and bot tokens."
nav: "Sign-in and tokens"
doc_version: 1
last_updated: 2026-10-16
---

# Sign-in and tokens

sblurp.chat is an OAuth 2.0 authorization server. It signs people in and gives the app a token for each community server. Community servers check those tokens with sblurp.chat's public keys. Bots use their own tokens instead.

## The flow

1. The app sends the person to sign in once, with Authorization Code and PKCE:

   ```http
   GET https://sblurp.chat/oauth/authorize?response_type=code&client_id=sblurp-web
       &redirect_uri=...&code_challenge=...&code_challenge_method=S256&state=...
   ```

2. sblurp.chat redirects back with `code`, `state` and `iss`. The app trades the code:

   ```http
   POST https://sblurp.chat/oauth/token
   grant_type=authorization_code&client_id=sblurp-web&code=...&redirect_uri=...&code_verifier=...
   ```

   The reply has a `refresh_token` and an `access_token` for sblurp.chat itself.

3. For each community server, the app asks for a token with that server as the audience:

   ```http
   POST https://sblurp.chat/oauth/token
   grant_type=refresh_token&client_id=sblurp-web&refresh_token=...&audience=https://chat.example.com
   ```

   The reply has a new refresh token and an access token for that server only.

4. The app sends the access token to the server as `Authorization: Bearer <token>`.

The only client is the web app, `sblurp-web`, with fixed return addresses. PKCE with `S256` is required. A code works once, within 60 seconds.

## Token reply

```json
{"access_token": "eyJ...", "token_type": "Bearer", "expires_in": 900, "refresh_token": "..."}
```

## Access tokens

An access token is a JWT signed with EdDSA (Ed25519). It lasts 15 minutes. Its claims:

| Claim | What |
|---|---|
| `iss` | The issuer, `https://sblurp.chat`. |
| `sub` | The account id. Stable. |
| `aud` | The server's base URL, or the issuer for sblurp.chat's own API. |
| `exp`, `iat` | Expiry and issue time, in Unix seconds. |
| `jti` | A unique id. |
| `preferred_username` | The username. |
| `email_verified` | Whether the email address is confirmed. |
| `age_over_13`, `age_over_18` | What the person declared at sign-up. |

The token carries no profile. The app sends the profile in `Join`, after the person agrees.

## Refresh tokens

- Opaque, and good for 60 days.
- Rotated on every use: each refresh returns a new one.
- Sending the same token again within 10 seconds is treated as a retry and gets the same new token.
- A used token that comes back later means someone else has a copy. sblurp.chat then revokes every token in that chain.

Revoke a refresh token, and its whole chain, with RFC 7009:

```http
POST https://sblurp.chat/oauth/revoke
token=...
```

It always answers 200.

## How a server checks a token

1. The `iss` must be in the server's trusted issuers. It checks this before fetching any keys.
2. It fetches `{iss}/.well-known/jwks.json` and caches the keys for an hour. An unknown `kid` makes it fetch again, at most every 30 seconds.
3. It checks the signature (only `alg: EdDSA`), then `aud` against its own base URL, then `exp`, `iat` and `nbf`, with 60 seconds of clock skew.

A token for one community is useless at another. A server knows a person by `(iss, sub)`, never by `sub` alone.

## sblurp.chat endpoints

| Endpoint | What |
|---|---|
| `GET /oauth/authorize` | Starts sign-in. |
| `POST /oauth/token` | `authorization_code` and `refresh_token` grants. |
| `POST /oauth/revoke` | Revokes a refresh token chain. |
| `GET /api/me` | The account behind an access token for sblurp.chat: `id`, `username`, `email_verified`, `display_name`, `avatar_url`, `bio`, `pronouns`. |
| `GET /.well-known/jwks.json` | Public signing keys. |
| `GET /.well-known/openid-configuration` | Discovery document. |

Errors are JSON, such as `{"error": "invalid_grant", "error_description": "code expired"}`. The codes are `invalid_client`, `invalid_grant`, `invalid_target` (a bad `audience`), `unsupported_grant_type` and `invalid_token`.

## Bot tokens

A bot token starts with `sbb_`. An admin makes it with `BotService.CreateBot`, and it is shown once. The server stores only its SHA-256 hash. It works only on the server that made it. See [Bot tokens](/docs/bot-tokens).

Tools and agents can read every call and type from [schema.json](/docs/api/schema.json).

## Sitemap

- [Sblurp: chat for communities](https://sblurp.chat/index.md): Sblurp is group chat with channels, threads and roles. Each community runs on its own server, and one Sblurp account signs you in to all of them.
- [About Sblurp](https://sblurp.chat/about.md): Why Sblurp exists: chat for communities that each run their own server, with no ads, no unasked-for AI and an honest word on encryption.
- [Privacy at Sblurp](https://sblurp.chat/privacy.md): What sblurp.chat stores about you, what it never stores, what it shares with communities you join, and how to get a copy or delete it.
- [Terms of use](https://sblurp.chat/terms.md): The terms for a sblurp.chat account: who can sign up, what you must not do, and what we do and do not promise. A first draft.
- [Create your Sblurp account](https://sblurp.chat/signup.md): Create a Sblurp account: one account for every Sblurp community you join. You need an email, a username, a password and to be 13 or older.
- [Sign in to Sblurp](https://sblurp.chat/login.md): Sign in to your Sblurp account with your email or username and password, or with a passkey. One account works in every Sblurp community.
- [Reset your password](https://sblurp.chat/forgot.md): Forgot your Sblurp password? Type the email you signed up with and we send a link to choose a new one. The link works once, for one hour.
- [Sblurp docs](https://sblurp.chat/docs.md): Sblurp documentation: how accounts and communities work, how to run a community server, how to add bots, and the full API reference.
- [Accounts and communities](https://sblurp.chat/docs/accounts.md): How a Sblurp account relates to the communities you join: what sblurp.chat keeps, what each community server sees, and what stays private.
- [Join a community](https://sblurp.chat/docs/join.md): Join a Sblurp community: add it by address or invite link, answer its questions, choose what to share, and join.
- [Sblurp glossary](https://sblurp.chat/docs/glossary.md): The words the Sblurp docs use, from account and community to issuer, track, bot token and seq, each with a link to the page that explains it.
- [Run a Sblurp community](https://sblurp.chat/docs/self-host.md): Run a Sblurp community on your own server: one small program and one data folder. What you need, how to start it, and what it stores.
- [Run a server](https://sblurp.chat/docs/create.md): For developers: start your own Sblurp community. Run the open-source server, join it first to become the owner, then set it up and invite people.
- [Set up a server with AI](https://sblurp.chat/docs/ai.md): Not a developer? Ask an AI assistant such as Claude to set up your Sblurp community server.
- [Sblurp server sizes and costs](https://sblurp.chat/docs/hosting.md): Which server size to rent for a Sblurp community and what it costs each month: measured limits per size and prices at Fly.io, DigitalOcean, Hetzner, OVHcloud and AWS Lightsail.
- [Run Sblurp on Render](https://sblurp.chat/docs/render.md): Run a Sblurp community server on Render: one Starter web service with a persistent disk, the released image, and optional backups to Cloudflare R2.
- [Run Sblurp on Railway](https://sblurp.chat/docs/railway.md): Run a Sblurp community server on Railway: one service from the released image, a volume for /data, and optional backups to Cloudflare R2.
- [Run Sblurp on Fly.io](https://sblurp.chat/docs/fly.md): Run a Sblurp community server on Fly.io: one always-on machine with a volume, h2c streaming, and optional backups to Cloudflare R2.
- [Run Sblurp on any VPS](https://sblurp.chat/docs/vps.md): Run a Sblurp community server on a small virtual server from Hetzner, OVHcloud, Akamai Linode, Vultr, DigitalOcean or any other host, with Docker Compose.
- [Run Sblurp with Docker and Compose](https://sblurp.chat/docs/docker.md): Run a Sblurp community server with Docker Compose and Caddy: the files, the settings, where the data lives, and how to run it behind your own proxy.
- [Run Sblurp with Podman](https://sblurp.chat/docs/podman.md): Run a Sblurp community server with a Podman Quadlet file, with daily automatic updates that roll back when a new image does not start.
- [Sblurp server configuration](https://sblurp.chat/docs/configuration.md): Every flag and environment variable of the Sblurp community server, with defaults, plus the backup variables of the container image and the built-in limits.
- [TLS and reverse proxies for Sblurp](https://sblurp.chat/docs/proxies.md): Put Caddy, nginx or Cloudflare in front of a Sblurp community server without breaking live streams: h2c, no buffering, no compression.
- [Back up a Sblurp server](https://sblurp.chat/docs/backups.md): Back up a Sblurp community server: Litestream copies the database to Cloudflare R2 within 10 seconds, an encrypted backup tool copies the files, or make a plain copy. How to restore.
- [Update a Sblurp server](https://sblurp.chat/docs/updates.md): Release tracks for the Sblurp server image, the daily update check, manual and automatic updates, and how to roll back.
- [Verify a Sblurp release](https://sblurp.chat/docs/provenance.md): Check that a Sblurp server image was built by the public release workflow, with GitHub attestations or cosign.
- [Troubleshooting a Sblurp server](https://sblurp.chat/docs/troubleshooting.md): Fix common problems with a Sblurp community server: sign-in fails, messages arrive late, certificates, file links, and where the logs are.
- [Invites in Sblurp](https://sblurp.chat/docs/invites.md): Make a Sblurp community invite only, create invite links with an expiry and a use limit, and revoke them.
- [Moderation and roles in Sblurp](https://sblurp.chat/docs/moderation.md): Permissions in a Sblurp community (owner, admin, moderator, member), custom roles that limit channels, channel modes, kicks and bans.
- [Safety in Sblurp](https://sblurp.chat/docs/safety.md): Who can read your messages, how to protect your account, what to do about unwanted messages, how to report a message, what moderators can do, age rules, and how to reach sblurp.chat.
- [Your data in Sblurp](https://sblurp.chat/docs/data.md): What sblurp.chat stores about your account, what a community server stores, who controls each, how long data is kept, backups, export and deletion.
- [Sblurp bots](https://sblurp.chat/docs/bots.md): Two ways to add a bot to a Sblurp community: a JavaScript plugin on the server, or a program anywhere that uses the API with a bot token.
- [Sblurp bot tokens](https://sblurp.chat/docs/bot-tokens.md): Make a Sblurp bot with a token, run the example bot, and call the API from any language: subscribe to events and reply to mentions.
- [Connect an AI agent to Sblurp](https://sblurp.chat/docs/agents.md): How to connect a self-hosted AI agent, such as OpenClaw, NanoClaw or Hermes Agent, to a Sblurp community with a bot token. No built-in connector exists yet.
- [Use Sblurp from Claude Code and other MCP clients](https://sblurp.chat/docs/mcp.md): Add a Sblurp community to Claude Code, Claude Desktop, VS Code or another MCP client by URL, sign in with your sblurp.chat account, and let the agent read and post as you.
- [Sblurp plugins](https://sblurp.chat/docs/plugins.md): Write a Sblurp bot as one JavaScript file and install it in the app, with the API or in the plugins folder: hooks for joins, messages, slash commands and timers, replies, limits and the dice example.
- [Sblurp API: protocol and transport](https://sblurp.chat/docs/api.md): How clients and bots talk to a Sblurp community server: Connect RPC over HTTP, the proto contract, JSON and binary bodies, auth, streaming and versioning.
- [Sblurp API explorer](https://sblurp.chat/docs/api/explorer.md): Browse and try every call of the Sblurp community server API in your browser, from the OpenAPI 3.1 description in openapi.json.
- [Sblurp API: sign-in and tokens](https://sblurp.chat/docs/api/auth.md): How sign-in works across Sblurp: OAuth 2.0 with PKCE at sblurp.chat, per-server access tokens, JWT claims, refresh token rotation, JWKS, and bot tokens.
- [Sblurp API: events](https://sblurp.chat/docs/api/events.md): The Sblurp live event stream: Subscribe, sequence numbers, replay and resync, heartbeats, every event kind, who receives it, and unread counts.
- [Sblurp API: uploads and files](https://sblurp.chat/docs/api/files.md): The plain HTTP endpoints of a Sblurp community server: uploads, signed file URLs, custom emoji, invite links and the health check.
- [Sblurp API: errors and rate limits](https://sblurp.chat/docs/api/errors.md): Error codes the Sblurp community server returns, what each one means for a client, and the rate limits for people and bots.
- [ServerService API reference](https://sblurp.chat/docs/api/server-service.md): Every ServerService call of the Sblurp community server: what it does, who may call it, and its request and response fields.
- [ChatService API reference](https://sblurp.chat/docs/api/chat-service.md): Every ChatService call of the Sblurp community server: what it does, who may call it, and its request and response fields.
- [BotService API reference](https://sblurp.chat/docs/api/bot-service.md): Every BotService call of the Sblurp community server: what it does, who may call it, and its request and response fields.
- [API types](https://sblurp.chat/docs/api/types.md): The messages and enums the Sblurp community server API shares between calls, with every field.
