API Authentication
BadgerPanel's REST API supports two authentication methods: JWT tokens for user-context operations and API keys for programmatic access. Both methods provide access to the same endpoints, with permissions determined by the authenticated user's role.
Authentication Methods
| Method | Use Case | Token Format |
|---|---|---|
| JWT (Bearer Token) | Web frontend, interactive sessions | Short-lived access token + refresh token |
| API Key | Scripts, bots, integrations, CI/CD | Long-lived key with scoped permissions |
JWT Authentication
JWT (JSON Web Token) authentication is the primary method used by the web frontend. It uses short-lived access tokens paired with longer-lived refresh tokens.
How It Works
1. User sends credentials (email + password) to /api/v1/auth/login
2. API validates credentials and returns:
- access_token (short-lived, default 15 minutes)
- refresh_token (longer-lived, default 7 days)
3. Client includes the access token in subsequent requests
4. When the access token expires, the client uses the refresh token
to obtain a new access token from /api/v1/auth/refreshLogin
curl -X POST "https://panel.your-domain.com/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "your-password"
}'Response:
{
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 900
}
}Using the Access Token
Include the access token in the Authorization header:
curl "https://panel.your-domain.com/api/v1/servers" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."Refreshing Tokens
When the access token expires (HTTP 401 response), use the refresh token:
curl -X POST "https://panel.your-domain.com/api/v1/auth/refresh" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "eyJhbGciOiJIUzI1NiIs..."
}'Response:
{
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 900
}
}Token Rotation
Each refresh request returns both a new access token and a new refresh token. The old refresh token is invalidated, providing token rotation for security.
Two-Factor Authentication
If the user has 2FA enabled, the login response will indicate a 2FA challenge:
{
"data": {
"requires_2fa": true,
"token": "temporary-2fa-token"
}
}Complete the 2FA challenge:
curl -X POST "https://panel.your-domain.com/api/v1/auth/2fa/verify" \
-H "Content-Type: application/json" \
-d '{
"token": "temporary-2fa-token",
"code": "123456"
}'Logout
Invalidate the current session:
curl -X POST "https://panel.your-domain.com/api/v1/auth/logout" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."JWT Token Configuration
Token lifetimes are configurable via environment variables:
| Variable | Description | Default |
|---|---|---|
JWT_ACCESS_EXPIRY | Access token lifetime | 15m |
JWT_REFRESH_EXPIRY | Refresh token lifetime | 7d |
JWT_SECRET | Secret key for signing tokens | Required |
JWT Secret
The JWT_SECRET must be a cryptographically strong random string of at least 32 characters. Changing this value invalidates all existing sessions. Never share or expose this value.
API Key Authentication
API keys are designed for programmatic access: scripts, bots, monitoring tools, and third-party integrations. They are long-lived and do not require the login/refresh flow.
Creating an API Key
Users create API keys from their account dashboard:
- Navigate to Account > API Keys
- Click Create API Key
- Configure the key:
| Field | Description |
|---|---|
| Description | What this key is used for (e.g., "Discord Bot") |
| Allowed IPs | Optional IP whitelist (leave empty to allow all) |
- Click Create
- Copy the key immediately -- it is shown only once and stored as a SHA-256 hash
The key format is a long random string prefixed with bp_:
bp_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6Using an API Key
Include the API key in the Authorization header with the Bearer scheme:
curl "https://panel.your-domain.com/api/v1/servers" \
-H "Authorization: Bearer bp_a1b2c3d4e5f6..."API Key Permissions
API keys inherit the permissions of the user who created them. An admin user's API key has admin-level access; a regular user's key has standard user access.
Least Privilege
Create API keys on accounts with only the permissions needed for the integration. Avoid using admin API keys unless necessary.
IP Whitelisting
For additional security, restrict API keys to specific IP addresses:
- When creating the key, enter one or more allowed IPs
- Requests from non-whitelisted IPs are rejected with HTTP 403
- This is especially important for keys with admin access
Revoking API Keys
To revoke an API key:
- Navigate to Account > API Keys
- Click Delete on the key to revoke
- The key is immediately invalidated
Admins can also revoke any user's API keys from Admin > Users > [User] > API Keys.
Rate Limiting
All API requests are rate-limited to prevent abuse and ensure fair usage.
Rate Limit Tiers
| Endpoint Category | Default Limit | Notes |
|---|---|---|
| General API | 60 requests/minute | Per user |
| Authentication | 10 requests/minute | Per IP address |
| Server Console | 30 commands/minute | Per server |
| File Upload | 10 requests/minute | Per server |
| Backup Creation | 5 requests/minute | Per server |
Role-Based Multipliers
Each user role has a rate limit multiplier that adjusts the base limit:
| Role | Multiplier | Effective Limit |
|---|---|---|
| User | 1.0x | 60/min |
| Moderator | 1.5x | 90/min |
| Admin | 2.0x | 120/min |
| Custom Role | Configurable | Varies |
Rate Limit Headers
Every API response includes rate limit headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1700000060
Retry-After: 45| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Retry-After | Seconds to wait before retrying (only on 429 responses) |
Handling Rate Limits
When you exceed the rate limit, the API returns HTTP 429:
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Please retry after 45 seconds."
}
}Best practices for handling rate limits:
- Check
X-RateLimit-Remainingbefore making requests - When receiving a 429, wait for the
Retry-Afterduration - Implement exponential backoff for retry logic
- Cache responses when possible to reduce request volume
# Example: Python retry logic with backoff
import time
import requests
def api_request(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after)
continue
return response
raise Exception("Max retries exceeded")Security Best Practices
Use API keys for automation -- Avoid storing email/password in scripts. Use API keys instead.
Rotate keys periodically -- Delete old keys and create new ones on a regular schedule.
Use IP whitelisting -- Restrict API keys to known IP addresses wherever possible.
Monitor key usage -- Review API key activity and revoke unused keys.
Use HTTPS only -- Never send authentication credentials or tokens over unencrypted HTTP.
Store tokens securely -- Never log, commit, or expose access tokens or API keys in client-side code, logs, or version control.
Handle token expiry gracefully -- Implement proper refresh logic for JWT tokens to avoid storing long-lived credentials.
Next Steps
- API Endpoints -- Available endpoints and response formats
- Configuration -- JWT and rate limit configuration