# API Reference
URL: /docs/api
Complete REST API documentation for TokenPass Server
TokenPass Server exposes a REST API on `http://localhost:21000`. All endpoints are prefixed with `/api/` and accept/return JSON.
TokenPass uses a two-step authentication: first unlock the wallet with `/api/login`, then get access tokens with `/api/auth`.
## Quick Start
### Register a Wallet (First Time Only)
```bash
curl -X POST http://localhost:21000/api/register \
-H "Content-Type: application/json" \
-d '{
"password": "my-secure-password",
"displayName": "Alice"
}'
```
### Login (Unlock Wallet)
```bash
curl -X POST http://localhost:21000/api/login \
-H "Content-Type: application/json" \
-d '{"password": "my-secure-password"}'
```
### Get an Access Token
```bash
curl -X POST http://localhost:21000/api/auth \
-H "Content-Type: application/json" \
-d '{
"password": "my-secure-password",
"host": "example.com",
"expire": "1h",
"scopes": "sign,encrypt"
}'
```
### Use the Token
```bash
curl -X POST http://localhost:21000/api/sign \
-H "Content-Type: application/json" \
-H "Authorization: YOUR_ACCESS_TOKEN" \
-d '{"message": "Hello World"}'
```
## Endpoints
Register, login, logout, status, export
Generate OAuth-style tokens for hosts
Sign and encrypt messages
Read and update BAP profile
***
## Wallet Management
### POST /api/register
Create a new wallet with an encrypted master seed. Only call this once during initial setup.
```json
{
"password": "string (required)",
"displayName": "string (optional)",
"paymail": "string (optional)",
"logo": "string (optional, URL or data URI)"
}
```
| Field | Type | Description |
| ------------- | ------ | ----------------------------------- |
| `password` | string | Password to encrypt the master seed |
| `displayName` | string | Your display name |
| `paymail` | string | Your paymail address |
| `logo` | string | Profile image URL or data URI |
```json
{
"success": true
}
```
***
### POST /api/login
Unlock the wallet by decrypting the master seed.
```json
{
"password": "string (required)"
}
```
```json
{
"success": true
}
```
Must be called after server restart or `/api/logout` before using protected endpoints.
***
### POST /api/logout
Lock the wallet by clearing the in-memory decrypted seed.
```json
{
"success": true
}
```
***
### GET /api/status
Check the current wallet status.
```json
{
"seed": true,
"unlocked": true,
"keys": [...],
"states": [...]
}
```
| Field | Type | Description |
| ---------- | ------- | ------------------------------------- |
| `seed` | boolean | `true` if wallet exists |
| `unlocked` | boolean | `true` if wallet is unlocked |
| `keys` | array | Derived keys (empty if locked) |
| `states` | array | Access token states (empty if locked) |
***
### POST /api/export
Export the master seed and mnemonic phrase.
Never share your seed or mnemonic. Anyone with access has full control of your identity.
```json
{
"password": "string (required)"
}
```
```json
{
"seed": "hex-encoded-seed",
"mnemonic": "twelve or twenty-four word phrase"
}
```
***
## Access Tokens
### POST /api/auth
Generate an OAuth-style access token for a specific web host.
```json
{
"password": "string (required)",
"host": "string (required)",
"expire": "string (optional, default: 'once')",
"scopes": "string (optional, comma-separated)",
"icon": "string (optional)"
}
```
**Expire Options:**
| Value | Duration |
| --------- | -------------------- |
| `once` | 10 seconds (default) |
| `1h` | 1 hour |
| `1d` | 1 day |
| `1w` | 1 week |
| `1m` | 1 month |
| `forever` | No expiration |
**Scope Options:**
| Scope | Description |
| --------------- | ----------------------- |
| `sign` | Sign messages |
| `encrypt` | Encrypt messages |
| `decrypt` | Decrypt messages |
| `read_profile` | Read BAP identity |
| `write_profile` | Modify BAP identity |
| `read_state` | Read per-host state |
| `write_state` | Write per-host state |
| `fund` | Request funding/payment |
| `transfer` | Transfer tokens/assets |
```json
{
"success": true,
"accessToken": "uuid-v4-token",
"expireTime": 1234567890123,
"host": "example.com"
}
```
***
## Cryptographic Operations
### POST /api/sign
Sign a message with the derived Bitcoin private key for the authenticated host.
Requires `Authorization: ACCESS_TOKEN` header (no "Bearer" prefix)
```json
{
"message": "string (required)",
"encoding": "string (optional, default: 'utf8')"
}
```
| Field | Type | Description |
| ---------- | ------ | -------------------------- |
| `message` | string | The message to sign |
| `encoding` | string | `utf8`, `hex`, or `base64` |
```json
{
"address": "1BitcoinAddress...",
"sig": "signature-string",
"message": "original-message",
"ts": 1234567890123
}
```
***
### POST /api/encrypt
Encrypt a message using ECIES.
Requires `Authorization: ACCESS_TOKEN` header with `encrypt` scope
```json
{
"message": "string (required)"
}
```
```json
{
"encrypted": "encrypted-message-data"
}
```
***
## Identity Management
### GET /api/profile
Retrieve the global BAP identity profile. No authentication required.
```json
{
"host": "global",
"displayName": "Alice",
"paymail": "alice@example.com",
"logo": "https://...",
"bapID": "identity-key-string"
}
```
***
### POST /api/profile
Update the global BAP identity profile.
```json
{
"displayName": "string (optional)",
"paymail": "string (optional)",
"logo": "string (optional)",
"customField": "any value"
}
```
```json
{
"success": true
}
```
***
## Error Handling
All errors return a consistent format:
```json
{
"error": "Error message description",
"code": 1,
"success": false
}
```
| Code | Description |
| ---- | ---------------------------- |
| `1` | Wallet is locked |
| `2` | Missing authorization header |
| `3` | Invalid access token |
| `5` | Access token has expired |
| HTTP Status | Description |
| ----------- | ---------------------------------------- |
| `200` | Success |
| `400` | Bad Request - missing required fields |
| `401` | Unauthorized - invalid password or token |
| `417` | Expectation Failed - wallet not created |
| `500` | Internal Server Error |
## Configuration
### CORS
Configure allowed origins:
```bash
TOKENPASS_ORIGIN_WHITELIST=https://app1.com,https://app2.com bun dev
```
### Storage
All data is stored in `~/.tokenpass/`:
| File | Description |
| ---------- | ----------------------------------- |
| `seed.db` | Encrypted master seed (AES-256-CBC) |
| `keys.db` | Derived Bitcoin keys per host |
| `state.db` | Access tokens and per-host state |
---
# Authentication
URL: /docs/authentication
How Bitcoin-based authentication works in TokenPass
# Authentication
TokenPass uses Bitcoin cryptography for authentication. This provides several advantages over traditional auth systems.
## How It Works
1. **Key Derivation** - TokenPass uses Type42 (BRC-42/BRC-43) to derive unique keys for each application
2. **Message Signing** - Authentication is done by signing messages with BSM (Bitcoin Signed Message)
3. **Verification** - Any party can verify signatures using only the public key
## Flow
>TP: 1. Request signature
TP-->>App: 2. Return signature
App->>Server: 3. Send request with signature
Server-->>App: 4. Verify & respond
`}
/>
## Per-App Key Isolation
Each website gets a unique derived key. This means:
* Apps can't track you across sites
* Compromising one app doesn't compromise others
* You maintain a single master identity
## OAuth-Compatible
TokenPass acts as an OAuth provider, making it easy to integrate with existing auth flows:
```typescript
// Redirect to TokenPass for auth
window.location.href = 'http://localhost:21000/auth?' + new URLSearchParams({
redirect: 'https://myapp.com/callback',
scopes: 'sign,encrypt'
});
```
## Token Scopes
Available scopes:
* `sign` - Sign messages
* `encrypt` - Encrypt/decrypt data
* `identity` - Read identity info
---
# TokenPass Documentation
URL: /docs
Your personal identity server with Bitcoin-backed authentication
# Welcome to TokenPass
TokenPass is your personal identity server. Be your own OAuth provider with Bitcoin-backed authentication. No cloud accounts, no centralized dependencies.
## Quick Start
```bash
bunx @sigma-auth/tokenpass-server
```
This starts the TokenPass server on `http://localhost:21000`.
## Core Concepts
* **Type42 (BRC-42/BRC-43)** - Key derivation for per-app isolation
* **BAP** - Bitcoin Attestation Protocol for identity
* **BSM** - Bitcoin Signed Message for authentication
* **ECIES** - End-to-end encryption using Bitcoin keys
## Next Steps
* [API Reference](/docs/api) - Complete API documentation
* [Authentication](/docs/authentication) - How authentication works
* [Integration](/docs/integration) - Integrate with your app
---
# Integration Guide
URL: /docs/integration
Integrate TokenPass authentication into your application
# Integration Guide
This guide shows how to integrate TokenPass into your application.
## Using Better Auth Plugin
The easiest way to integrate TokenPass is with the Better Auth plugin:
```bash
bun add @sigma-auth/better-auth-plugin better-auth
```
### Server Setup
```typescript
import { betterAuth } from "better-auth";
import { sigmaAuth } from "@sigma-auth/better-auth-plugin";
export const auth = betterAuth({
plugins: [
sigmaAuth({
tokenpassUrl: "http://localhost:21000"
})
]
});
```
### Client Setup
```typescript
import { createAuthClient } from "better-auth/client";
import { sigmaAuthClient } from "@sigma-auth/better-auth-plugin/client";
export const authClient = createAuthClient({
plugins: [sigmaAuthClient()]
});
// Sign in with TokenPass
await authClient.signIn.sigma();
```
## Direct API Integration
If you prefer direct integration:
### 1. Request Authentication
```typescript
// Redirect user to TokenPass
const params = new URLSearchParams({
redirect: 'https://yourapp.com/callback',
host: 'yourapp.com',
scopes: 'sign'
});
window.location.href = `http://localhost:21000/auth?${params}`;
```
### 2. Handle Callback
```typescript
// On your callback page
const url = new URL(window.location.href);
const signature = url.searchParams.get('signature');
const address = url.searchParams.get('address');
const message = url.searchParams.get('message');
// Verify the signature on your server
const verified = await verifySignature({ signature, address, message });
```
### 3. Verify Signature
Use the `bsv` library to verify:
```typescript
import { BSM } from '@bsv/sdk';
function verifySignature({ signature, address, message }) {
return BSM.verify(message, signature, address);
}
```
## React Hook Example
```typescript
import { useState } from 'react';
export function useTokenPass() {
const [user, setUser] = useState(null);
const signIn = () => {
const params = new URLSearchParams({
redirect: window.location.origin + '/auth/callback',
host: window.location.host,
scopes: 'sign'
});
window.location.href = `http://localhost:21000/auth?${params}`;
};
const handleCallback = async (searchParams) => {
const signature = searchParams.get('signature');
const address = searchParams.get('address');
// Verify with your backend
const res = await fetch('/api/auth/verify', {
method: 'POST',
body: JSON.stringify({ signature, address })
});
if (res.ok) {
setUser(await res.json());
}
};
return { user, signIn, handleCallback };
}
```
## Security Considerations
* Always verify signatures on your server, not the client
* Use HTTPS in production
* Validate the `host` parameter matches your domain
* Set appropriate token expiry times