Sari la conținut

API reference

Acest conținut nu este încă disponibil în limba selectată.

The razorBridge REST API is what the CLI uses, and it is public: anything rb does, your own code can do.

https://api.razorbridge.eu/v1

A request to the bare root of that host returns a small JSON index of the main endpoint groups. There is a staging deployment at https://api.staging.razorbridge.eu/v1 with separate data.

Two conventions to note before you start:

  • Paths under /events/, /blades/, /credits/, /gpu-types/ and /auth/ end in a slash. The /gate/… paths do not. Getting this wrong produces a redirect or a 404.
  • Every response is JSON. Errors are always {"error": "<message>"}, except for inference calls, which pass the upstream provider’s error body through unchanged.

There are two kinds of credential, both presented as Authorization: Bearer <…>.

Credential Obtained from Valid for
Session token The device flow below, or rb auth login Every endpoint except the two marked gate key
Gate key POST /gate/keys or the web app POST /gate/chat/completions and GET /gate/models only

Presenting the wrong kind is a 401, which is the usual cause of an unexpected Invalid API key.

Session access tokens expire after 1 hour; refresh tokens after 30 days.

Made for command-line and headless clients: the client never sees a password.

POST /auth/device/ (no authentication)

Response:

Field Notes
device_code Secret. Poll with this
user_code 8 characters. Show it to the user to type in the browser
verification_uri Where the user goes to approve
expires_in 900 — the code is good for 15 minutes
interval 5 — suggested seconds between polls
Terminal window
curl -X POST https://api.razorbridge.eu/v1/auth/device/

Then poll, sending the device_code:

POST /auth/token/ (no authentication)
{"device_code": "…"}
Status Meaning
200 Approved. Returns access_token, refresh_token, token_type, expires_in
428 authorization_pending — keep polling
410 The code expired. Start again
404 Unknown device_code

The user must be signed in to razorBridge and type the user_code on the Authorize razorBridge CLI page. Approving creates their account, and its €10 signup credit, if they did not already have one.

POST /auth/refresh/ {"refresh_token": "…"} → access_token, token_type, expires_in
POST /auth/revoke/ Bearer session token → {"revoked": true, "sessions_revoked": n}
GET /auth/me/ Bearer session token

POST /auth/revoke/ revokes every session belonging to the caller, not just the token presented — it is a sign-out-everywhere, and the right response to a leaked token. A token that is already invalid gets {"revoked": false}.

GET /auth/me/ returns:

{
"user": {"id": 1, "email": "you@example.org", "name": "Your Name"},
"account": {"id": "", "name": "Your Account", "balance_eur": "10.0000"}
}

Monetary values are strings throughout the API, to avoid float rounding.

Returns two lists, because your relationship to an event changes what you can see:

{
"participating": [{"id": "", "name": "", "slug": "", "status": "running",
"starts_at": "", "ends_at": ""}],
"organizing": [{"id": "", "name": "", "slug": "", "status": "scheduled",
"starts_at": "", "ends_at": "", "join_code": "ABCD-1234"}]
}

join_code appears only for events you organize — it is the credential that lets anyone join.

{"code": "ABCD-1234"}

Codes are upper-cased server-side, so case does not matter. Returns {"joined": true, "event": {"id", "name", "slug"}}.

Status Meaning
404 Event not found
409 Registration closed, Already registered, or Event is full
429 More than 20 join attempts from your IP in an hour

Detail for one event: id, name, slug, status, starts_at, ends_at, gpu_type, is_organizer, and bladenull until yours exists, otherwise {id, status, ip_address, gpu_type, time_remaining_seconds}. Organizers also get join_code.

Returns 403 Not your event to anyone who is neither a participant nor the organizing account, so events cannot be enumerated by slug.

Organizer only. Extends a running event:

{"minutes": 60}

minutes must be 30, 60 or 120. Returns {"extended": true, "new_ends_at", "estimated_cost_eur"}. A non-running event gives 409 Can only extend running events; someone else’s event gives 404.

Organizer only. Adds participants in bulk:

{"participants": [{"email": "alice@university.edu", "name": "Alice"},
{"email": "bob@university.edu"}]}

email is required; name defaults to the local part of the address. Returns {"created": n, "skipped": n}. Entries are skipped when they duplicate an existing participant, have no @, or would exceed the event’s participant cap — so re-posting the same roster is safe.

{"blades": [{"id": "", "event": "ML Workshop", "gpu_type": "gpu-l40sx1-48gb",
"status": "running", "ip_address": "", "started_at": ""}]}

Adds region, runtime_hours and, for event blades, time_remaining_seconds derived from the event’s end time. 403 Not your blade unless you are the assigned participant or the organizing account.

The connection credentials:

{"host": "", "port": 2201, "username": "user01",
"password": "", "ssh_command": "ssh -p 2201 user01@…"}

Only the assigned participant may read this — the organizing account may not. 409 Credentials not yet assigned means the blade is not ready. The first successful read is recorded against the participant.

{
"balance_eur": "8.4300",
"transactions": [
{"id": "", "type": "debit", "amount_eur": "1.4444", "source": "consumption",
"balance_after": "8.4300", "description": "", "created_at": ""}
]
}

Up to 50 entries, newest first. type is credit or debit; source values are listed in Credits and billing.

Available GPUs with the current published pricing, cheapest first:

{"gpu_types": [{"slug": "gpu-l40sx1-48gb", "display_name": "L40S", "vram_gb": 48,
"best_for": "Training & workshops",
"hourly_usd": "", "hourly_eur": ""}]}

hourly_eur is the authoritative rate, per GPU-hour, per blade. hourly_usd is a convenience conversion at a fixed reference rate, not a price you can pay in dollars.

This endpoint needs a session token, which also makes it the CLI’s connectivity probe: any HTTP response, including 401, proves the API is up.

The gate is an OpenAI-compatible surface. For SDK usage, point the client’s base_url at https://api.razorbridge.eu/v1/gate and let it append the rest.

Body and response follow the OpenAI chat-completions shape; model is required. The provider’s successful response is returned unchanged.

Status Meaning
400 Invalid JSON, or model required
401 Missing, unknown or revoked gate key
402 Insufficient credits, or Key budget limit exceeded
403 Model '…' not allowed for this key
502 Inference failed upstream

Streaming responses are not supported yet. Each successful call writes a usage record and deducts its cost from the account’s balance.

{"models": [{"id": "klusai/fast", "owned_by": "razorbridge"}]}

Model ids are aliases in the form klusai/<name>. The list reflects what the platform routes today, so read it rather than caching a catalogue.

A convenience wrapper for trying the gate before you have a key:

{"model": "klusai/fast", "message": "Hello"}

model defaults to klusai/fast; message defaults to Hello; a full messages array may be sent instead. Billed exactly like a normal call, and returns 402 with no balance.

{"usage": [{"id": "", "model": "klusai/fast", "prompt_tokens": 12,
"completion_tokens": 48, "cost_eur": "0.000123", "created_at": ""}]}

Up to 50 entries, newest first.

GET /gate/keys and POST /gate/keys — session token

Section titled “GET /gate/keys and POST /gate/keys — session token”

GET lists active keys: id, name, key_prefix, created_at, last_used_at.

POST creates one:

{"name": "Lab notebook", "allowed_models": ["klusai/fast"]}

Returns 201 with the full key, which is shown only in this response — afterwards only the prefix is retrievable. allowed_models is optional and is the only way to scope a key to specific models; omit it for unrestricted access. A per-key euro budget cap exists and is enforced, but cannot be set through this endpoint.

POST /gate/keys/<key_id>/revoke — session token

Section titled “POST /gate/keys/<key_id>/revoke — session token”

Returns {"revoked": true}, or 404 Key not found if the id does not belong to your account.

Code When
400 Malformed JSON or a missing/invalid field
401 Missing, wrong-type, expired or revoked credential
402 Out of credits, or a key budget exhausted
403 Authenticated, but not yours — someone else’s event, blade, or a disallowed model
404 Not found, or deliberately indistinguishable from not-yours
405 Wrong HTTP method
409 State conflict — registration closed, event full, already registered, credentials not ready, event not running
410 Device code expired
428 Device authorization still pending — keep polling
429 Rate limit exceeded
502 Upstream inference failure

Applied per client IP, in a fixed window, to the unauthenticated and abuse-prone endpoints:

Endpoint Limit
POST /auth/device/ 10 per hour
POST /auth/token/ 20 per hour
POST /auth/refresh/ 30 per hour
POST /events/join/ 20 per hour

Exceeding one returns 429 with Too many requests. Please slow down and try again later. Other endpoints are not rate-limited today; do not design against that.