Developers
API reference
Authenticate with a session or API key and use the implemented account, quote, instance and billing endpoints.
8 min read · UpdatedAuthentication
The base path is /api/v1. Browser requests use the HttpOnly session cookie created at login. Scripts can use Authorization: Bearer followed by an active API key. Keys have full account permissions and are shown once when created.
The local UI uses gh_demo_ keys. Revoking a key immediately prevents new authenticated requests using it. Do not put keys in URLs or browser-side bundles.
GET /api/v1/balance
Authorization: Bearer <your-api-key>
200 OK
{ "currency": "USD", "balanceCents": 50000, "derivedFrom": "ledger_entries" }Request and retry rules
POST and PATCH bodies are JSON objects, with Content-Type: application/json. Send {} for actions without parameters. Bodies are limited to 32 KiB of text. Responses use Cache-Control: no-store.
Deployment, manual renewal and withdrawal require an Idempotency-Key of 8–128 characters. Use a new key for a new intended operation and reuse the same key for its retry. Never reuse it with a different body. A replay response includes replayed: true.
Instance quotes calculate the current catalog price without reserving capacity. Send expectedPriceCents when deploying; a mismatch returns 409 so the price can be reviewed again.
POST /api/v1/instances
Content-Type: application/json
Idempotency-Key: <unique-operation-id>
Authorization: Bearer <your-api-key>
{
"sku": "nvidia-rtx-4090",
"gpuCount": 1,
"region": "dal",
"image": "pytorch",
"period": "week",
"options": [],
"sshKeyId": "<saved-key-id>",
"autoRenew": false,
"expectedPriceCents": 11000
}Implemented endpoints
All account resources are restricted to their owner. The availability endpoint is public and exposes the catalog snapshot, not a live hardware probe.
| Method | Path after /api/v1 | Purpose |
|---|---|---|
| POST | /auth/register · /auth/login | Username + password; create a session |
| POST | /auth/recover | Username + unused code + new password |
| POST | /auth/logout | Revoke the current browser session |
| GET | /me · /balance · /ledger | Account, balance and latest 100 entries |
| GET / DELETE | /sessions · /sessions/:id | List active sessions or revoke one |
| GET | /availability | Public catalog and regional stock snapshot |
| GET / POST | /deposit-quotes | List active quotes or create one with asset + desiredUsdCents |
| POST | /demo/confirm-deposit | Quote ID; local development only |
| GET | /deposits · /withdrawals | Latest 100 records for this account |
| POST | /withdrawals | Asset + destination + amountUsdCents; idempotent |
| POST | /instance-quotes | GPU, count, region, image, period and options |
| GET / POST | /instances | List allocations or deploy; deployment is idempotent |
| POST | /instances/:id/start · stop · release · renew | Lifecycle action; renewal is idempotent |
| PATCH | /instances/:id/auto-renew | Set enabled to true or false |
| GET / POST | /ssh-keys · /api-keys | List or create account keys |
| DELETE | /ssh-keys/:id · /api-keys/:id | Revoke a key |
Handle errors explicitly
Errors have {error, message}: a stable code and a readable explanation. 400 indicates invalid input, 401 missing or invalid authentication, 403 a rejected origin, 404 an unknown or unowned resource, 409 a balance/state/duplicate conflict, and 415 the wrong content type.
For an expired deposit quote, create another quote. For a changed instance state, reload the instance before deciding on another action. After a network interruption, reuse the operation key rather than creating a second charge.