API Authentication
The Expose API uses JWT tokens for user authentication and API keys for programmatic access.
Authentication Methods
JWT Tokens
Used for user sessions (web dashboard, app login):
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...API Keys
Used for tunnels and programmatic access:
Authorization: Bearer exp_k1_7f8a9b...Obtaining Credentials
Register a New User
POST /api/v1/auth/registerContent-Type: application/json
{ "email": "user@example.com", "password": "your-secure-password"}Response:
{ "user": { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "user@example.com", "created_at": "2024-01-15T10:30:00Z" }, "token": "eyJhbGciOiJIUzI1NiIs..."}Login
POST /api/v1/auth/loginContent-Type: application/json
{ "email": "user@example.com", "password": "your-secure-password"}Response:
{ "user": { "id": "550e8400-e29b-41d4-a716-446655440000", "email": "user@example.com", "created_at": "2024-01-15T10:30:00Z" }, "token": "eyJhbGciOiJIUzI1NiIs..."}Create API Key
POST /api/v1/api-keysAuthorization: Bearer <jwt_token>Content-Type: application/json
{ "name": "MacBook Pro"}Response:
{ "api_key": { "id": "660e8400-e29b-41d4-a716-446655440000", "name": "MacBook Pro", "key_prefix": "exp_k1_7f8a9b", "created_at": "2024-01-15T10:30:00Z", "last_used_at": null }, "key": "exp_k1_7f8a9b..."}Token Lifetime
| Token Type | Lifetime |
|---|---|
| JWT Token | 7 days |
| API Key | Until revoked |
Error Responses
401 Unauthorized
Missing or invalid token:
{ "error": "unauthorized", "message": "Invalid or expired token"}403 Forbidden
Valid token but insufficient permissions:
{ "error": "forbidden", "message": "You don't have permission to access this resource"}Best Practices
- Store tokens securely — Never in localStorage for web apps
- Use API keys for automation — Don’t use your JWT for scripts
- Rotate API keys — Create new keys periodically
- Revoke unused keys — Remove keys you no longer need
- Use HTTPS always — Tokens are sensitive data
Rate Limiting
API requests are rate limited:
| Endpoint | Limit |
|---|---|
| Auth endpoints | 10/minute |
| General API | 100/minute |
| Tunnel data | Unlimited |
When rate limited:
HTTP/1.1 429 Too Many RequestsRetry-After: 60
{ "error": "rate_limited", "message": "Too many requests, please try again later"}