All endpoints return application/json. Errors follow RFC 7807 (Problem+JSON). Every response carries an X-Request-Id header for correlation with the server-side audit log.
| Method | Path | Scope | Purpose |
|---|---|---|---|
| GET | /v1/health | public | Unauthenticated health check. |
| GET | /v1/me | any | Own account info + key metadata. |
| GET | /v1/products | read:products | List of all publicly listed products with prices. |
| GET | /v1/products/{id} | read:products | Product details including config options. |
| POST | /v1/orders | write:orders | Place an order. Idempotency-Key required. |
| GET | /v1/orders/{id} | read:orders | Status of an own order. |
| GET | /v1/services | read:services | List of own services (paginated). |
| GET | /v1/services/{id} | read:services | Details of an own service. |
| GET | /v1/services/{id}/credentials | read:credentials | Service credentials (separate scope, audit-logged). |
| POST | /v1/services/{id}/actions | write:services | Service action: start, stop, reboot, cancel (at the end of the billing period), cancel_revoke. |
| GET | /v1/billing/balance | read:billing | Credit balance. |
| GET | /v1/billing/invoices | read:billing | List of your invoices (paginated). |
| GET | /v1/billing/invoices/{id}/pdf | read:billing | Invoice PDF. |
| GET | /v1/webhooks | read:webhooks | Current webhook URL. |
| PUT | /v1/webhooks | write:webhooks | Set or unset webhook URL. |
Idempotency
POST /v1/orders and POST /v1/services/{id}/actions require an Idempotency-Key header (1 to 80 characters from [A-Za-z0-9_.-]). The key is bound to method, path and body. Repeating the same request with the same key within one hour returns the stored response; after that you get 410 with reason replay_stale and should send a new key. The same key with a different body or on another endpoint is rejected with 409 idempotency_conflict.
Rate limits
By default 60 requests per minute (plus a burst of 20) and 5,000 per day per key, 120 per minute per account across all keys and 600 per minute per source IP. When a limit is exceeded, you get HTTP 429 with a Retry-After header. The response headers X-RateLimit-Remaining and X-RateLimit-Reset show the current state of the key limit.

