Authentication
Every request to the Podstack Inference Cloud is authenticated with a Podstack API key sent as a bearer token. Keys are prefixed psk_.
Authorization: Bearer psk_xxxxxxxxxxxxxxxxxxxx
Only the Bearer scheme is accepted — there is no x-api-key header. A missing or empty token returns 401.
Create an API key
- Open the Podstack Inference portal and go to API Keys.
- Click Create API Key and enter a descriptive name (e.g.
production-app). - Choose an expiry: Never, 7 days, 30 days, 90 days, or 1 year.
- Click Create, then copy the key immediately — the full secret is shown only once.
You can hold up to 5 API keys at a time. Revoke an old one to create another.
The same
psk_key authenticates the Podstack CLI (podstack code,podstack models). You do not need a separate credential for the CLI.
Use the key
Store it in an environment variable and never commit it:
export PODSTACK_API_KEY="psk_xxxxxxxxxxxxxxxxxxxx"
curl
curl https://cloud.podstack.ai/infer/v1/chat/completions \
-H "Authorization: Bearer $PODSTACK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "<MODEL_ID>",
"messages": [{"role": "user", "content": "Hello!"}]
}'
OpenAI SDK (Python)
from openai import OpenAI
client = OpenAI(
base_url="https://cloud.podstack.ai/infer/v1",
api_key=os.environ["PODSTACK_API_KEY"],
)
Python requests
import os, requests
headers = {
"Authorization": f"Bearer {os.environ['PODSTACK_API_KEY']}",
"Content-Type": "application/json",
}
resp = requests.post(
"https://cloud.podstack.ai/infer/v1/chat/completions",
headers=headers,
json={"model": "<MODEL_ID>", "messages": [{"role": "user", "content": "Hi"}]},
)
Scoping requests to a project
To attribute usage and billing to a specific project, add the X-Project-ID header. It overrides the project encoded in the token:
curl https://cloud.podstack.ai/infer/v1/chat/completions \
-H "Authorization: Bearer $PODSTACK_API_KEY" \
-H "X-Project-ID: <PROJECT_ID>" \
-H "Content-Type: application/json" \
-d '{ "model": "<MODEL_ID>", "messages": [{"role":"user","content":"Hi"}] }'
Per-key limits
Each key carries independent limits, editable from the API Keys page:
| Limit | Default | Behavior when exceeded |
|---|---|---|
| Requests per minute | 60 | 429 rate_limit_exceeded |
| Max concurrency | 10 | 429 concurrency_limit_exceeded |
| Tokens per minute | Unlimited | 429 tokens_limit_exceeded |
| Monthly token limit | Unlimited | 429 monthly_quota_exceeded |
Rate-limited responses include X-RateLimit-Limit, X-RateLimit-Remaining, and Retry-After headers — respect Retry-After and back off exponentially. Two other per-key toggles are available: Store request data and Response cache (cache hits are served for free and don’t count against your limits).
Revoke a key
- Find the key in the API Keys list.
- Click Delete and confirm.
- The key is invalidated immediately — any request using it stops working on the next call.
Security best practices
- Never ship keys in client-side code. Call the API from a backend and proxy requests.
- Use environment variables, not hardcoded strings.
- Use separate keys for development, CI, and production so you can revoke one without disrupting the others.
- Rotate periodically — create a new key, roll it out, then delete the old one.
- Set a monthly token limit on each key as a spend guardrail.
Troubleshooting
401 Unauthorized — the key is missing, mistyped, expired, or revoked. Confirm the Bearer prefix and that there’s no stray whitespace.
402 insufficient_funds — your wallet balance is at or below zero. Top up under Pricing & Usage.
429 Too Many Requests — you hit a rate or quota limit. Check the code field (rate_limit_exceeded, tokens_limit_exceeded, concurrency_limit_exceeded, or monthly_quota_exceeded) and back off using Retry-After.
Next steps
- API Reference — full error format and route details.
- Pricing & Usage — the wallet and usage analytics.