Overview
The Grip AI REST API uses Bearer token authentication. All endpoints except /health and OAuth callbacks require a valid token in the Authorization header.
Tokens are auto-generated on first startup if not configured and use timing-safe comparison to prevent timing attacks.
Token Generation
Auto-Generation on First Run
When the API server starts without a configured auth_token, a new token is automatically generated with the format:
grip_<43-character-random-string>
The token is:
Printed once to stderr (save it immediately)
Persisted to ~/.grip/config.json for future startups
Never shown again (check config.json if lost)
Example startup output:
$ grip serve
AUTH TOKEN (save this — shown only once ):
grip_AbCdEfGhIjKlMnOpQrStUvWxYz1234567890-_AbCdEf
INFO: API server started on 127.0.0.1:8080
Save the auto-generated token immediately. It’s only displayed once on stderr. If lost, check ~/.grip/config.json or generate a new one manually.
Manual Token Configuration
Set a custom token in config.json:
{
"gateway" : {
"api" : {
"auth_token" : "your-secret-token-here"
}
}
}
Generate a secure token manually:
# Using openssl
openssl rand -base64 32
# Using Python
python3 -c "import secrets; print('grip_' + secrets.token_urlsafe(32))"
Use the grip_ prefix for consistency, though any string is accepted.
Using the Token
Include the token in the Authorization header with the Bearer scheme:
curl -X POST http://127.0.0.1:8080/api/v1/chat \
-H "Authorization: Bearer grip_AbCdEfGhIjKlMnOpQrStUvWxYz1234567890-_AbCdEf" \
-H "Content-Type: application/json" \
-d '{"message": "Hello"}'
Environment Variable
Store the token in an environment variable:
export GRIP_API_TOKEN = "grip_AbCdEfGhIjKlMnOpQrStUvWxYz1234567890-_AbCdEf"
curl -X POST http://127.0.0.1:8080/api/v1/chat \
-H "Authorization: Bearer $GRIP_API_TOKEN " \
-H "Content-Type: application/json" \
-d '{"message": "What time is it?"}'
Python Client Example
import os
import httpx
token = os.environ[ "GRIP_API_TOKEN" ]
base_url = "http://127.0.0.1:8080"
headers = {
"Authorization" : f "Bearer { token } " ,
"Content-Type" : "application/json"
}
with httpx.Client( base_url = base_url, headers = headers) as client:
response = client.post( "/api/v1/chat" , json = {
"message" : "List files in the workspace"
})
print (response.json())
JavaScript/TypeScript Client Example
const GRIP_API_TOKEN = process . env . GRIP_API_TOKEN ;
const BASE_URL = 'http://127.0.0.1:8080' ;
const headers = {
'Authorization' : `Bearer ${ GRIP_API_TOKEN } ` ,
'Content-Type' : 'application/json'
};
const response = await fetch ( ` ${ BASE_URL } /api/v1/chat` , {
method: 'POST' ,
headers ,
body: JSON . stringify ({
message: 'Analyze this repository'
})
});
const data = await response . json ();
console . log ( data );
Authentication Errors
Missing Token
Request without Authorization header:
curl http://127.0.0.1:8080/api/v1/chat
Response (401 Unauthorized):
{
"detail" : "Authentication required"
}
Headers:
Invalid Token
Request with incorrect token:
curl -X GET http://127.0.0.1:8080/api/v1/sessions \
-H "Authorization: Bearer wrong-token"
Response (401 Unauthorized):
{
"detail" : "Authentication required"
}
The error message is intentionally generic to avoid leaking authentication details.
Incorrect Bearer scheme:
# Missing "Bearer" prefix
curl -H "Authorization: grip_abc123" ...
# Wrong case
curl -H "Authorization: bearer grip_abc123" ...
Both return 401 with "detail": "Authentication required".
Token Security
Timing-Safe Comparison
All token comparisons use secrets.compare_digest() to prevent timing attacks. This ensures the comparison time is constant regardless of where the tokens differ.
Token Storage
The token is stored in ~/.grip/config.json with restrictive file permissions (0600) where supported:
$ ls -la ~/.grip/config.json
-rw------- 1 user user 1234 Feb 28 10:00 /home/user/.grip/config.json
Token Rotation
To rotate the token:
Generate a new token (see Manual Token Configuration)
Update config.json with the new token
Restart the API server : grip serve or restart the container
Update all clients with the new token
Changing the token invalidates all existing client credentials. Update all API clients before rotating.
Rate Limiting
Authenticated requests are subject to per-token rate limiting (default: 60 requests/minute).
See Overview - Rate Limits for details.
OAuth Endpoints
The OAuth callback endpoint is public (no Bearer auth required) because the OAuth provider redirects the user’s browser:
GET /api/v1/mcp/callback - No authentication required
All other MCP OAuth endpoints require Bearer auth.
See MCP Authentication for details.
Next Steps
Chat Endpoint Send authenticated messages to the agent
Sessions Manage conversation sessions