/health and /ready) require authentication via API key.
API Key Authentication
Pass your API key in theX-API-Key header. Each key is bound to a specific account.
Required Headers
Mutating operations (POST, DELETE, PATCH) return
400 Bad Request with "X-Project-ID required" if this header is missing.
Response Format
API responses return the same standard fields:Managing API Keys
API keys are managed from the Raff Dashboard:- Click API Keys in the sidebar (it’s a top-level menu item — not under Settings)
- Click Create API Key
- Name the key, pick its Account Role (and Project Role if not Owner), set an expiration, and click Create Key
- Copy the key immediately — it’s only shown once
Rate Limiting
Requests are rate-limited per API key. The tier is set on the key when it’s created (or by Raff support, on request).
How it actually works. The limiter is a sliding 1-second window plus a separate burst budget. As long as you stay within the per-second number, you’re fine. If you exceed it briefly, the burst budget covers you for short spikes — once that’s consumed, you start getting
429s until both windows recover. Burst budget refreshes on a 60-second window.
When rate-limited, the API returns:
- Honor the
Retry-Afterheader. It tells you exactly when to retry — don’t guess - Implement exponential backoff for
429and5xx:1s → 2s → 4s → 8s → 16scapped at ~60s - Coalesce reads — if you’re polling list endpoints every 100 ms in a loop, slow down. Most resources change on second-or-slower timescales
- Cache catalog data —
/api/v1/public/templates,/api/v1/public/pricing/vm, region lists, etc. don’t change minute-to-minute. Cache them locally for the lifetime of your script
Upgrading tier
Need more than Standard sustains? Two paths:
There’s no self-service upgrade today — it’s a support request because we want to understand the use case (and stop accidental loops from flooding the platform).
Calling the API from HTTP clients
Raff doesn’t ship a first-party SDK today. The API is plain REST + JSON, so any HTTP client works. The same headers + body apply across languages:- Python (requests)
- Node.js (fetch)
- Go (raff-go)
- Ruby (Net::HTTP)