Skip to content

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

MethodUse CaseToken Format
JWT (Bearer Token)Web frontend, interactive sessionsShort-lived access token + refresh token
API KeyScripts, bots, integrations, CI/CDLong-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/refresh

Login

bash
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:

json
{
  "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:

bash
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:

bash
curl -X POST "https://panel.your-domain.com/api/v1/auth/refresh" \
  -H "Content-Type: application/json" \
  -d '{
    "refresh_token": "eyJhbGciOiJIUzI1NiIs..."
  }'

Response:

json
{
  "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:

json
{
  "data": {
    "requires_2fa": true,
    "token": "temporary-2fa-token"
  }
}

Complete the 2FA challenge:

bash
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:

bash
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:

VariableDescriptionDefault
JWT_ACCESS_EXPIRYAccess token lifetime15m
JWT_REFRESH_EXPIRYRefresh token lifetime7d
JWT_SECRETSecret key for signing tokensRequired

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:

  1. Navigate to Account > API Keys
  2. Click Create API Key
  3. Configure the key:
FieldDescription
DescriptionWhat this key is used for (e.g., "Discord Bot")
Allowed IPsOptional IP whitelist (leave empty to allow all)
  1. Click Create
  2. 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_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6

Using an API Key

Include the API key in the Authorization header with the Bearer scheme:

bash
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:

  1. Navigate to Account > API Keys
  2. Click Delete on the key to revoke
  3. 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 CategoryDefault LimitNotes
General API60 requests/minutePer user
Authentication10 requests/minutePer IP address
Server Console30 commands/minutePer server
File Upload10 requests/minutePer server
Backup Creation5 requests/minutePer server

Role-Based Multipliers

Each user role has a rate limit multiplier that adjusts the base limit:

RoleMultiplierEffective Limit
User1.0x60/min
Moderator1.5x90/min
Admin2.0x120/min
Custom RoleConfigurableVaries

Rate Limit Headers

Every API response includes rate limit headers:

http
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1700000060
Retry-After: 45
HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetUnix timestamp when the window resets
Retry-AfterSeconds to wait before retrying (only on 429 responses)

Handling Rate Limits

When you exceed the rate limit, the API returns HTTP 429:

json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please retry after 45 seconds."
  }
}

Best practices for handling rate limits:

  1. Check X-RateLimit-Remaining before making requests
  2. When receiving a 429, wait for the Retry-After duration
  3. Implement exponential backoff for retry logic
  4. Cache responses when possible to reduce request volume
python
# 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

  1. Use API keys for automation -- Avoid storing email/password in scripts. Use API keys instead.

  2. Rotate keys periodically -- Delete old keys and create new ones on a regular schedule.

  3. Use IP whitelisting -- Restrict API keys to known IP addresses wherever possible.

  4. Monitor key usage -- Review API key activity and revoke unused keys.

  5. Use HTTPS only -- Never send authentication credentials or tokens over unencrypted HTTP.

  6. Store tokens securely -- Never log, commit, or expose access tokens or API keys in client-side code, logs, or version control.

  7. Handle token expiry gracefully -- Implement proper refresh logic for JWT tokens to avoid storing long-lived credentials.

Next Steps

BadgerPanel Documentation