Skip to content
Gezinme

Glac API

This is the reference of the Glac API: every call, what it takes and what it answers. The CLI, the SDKs and the MCP server call it. Download this description (OpenAPI 3.1).

The calls are arranged by product, as the docs are: Cube (its calls are /v1/apps: an app, which is what a Cube is, its versions and its instances), Sandbox, Drive (with the volumes underneath Drives), and then the platform's own calls: the project, keys, secrets, the account and its bill, events.

Address. Every path is under https://api.glac.ai.

One API in front of many machines. Sandboxes, and what is in them, live on machines (nodes, in the calls' own words). A call about a sandbox, a command, a file, a port's link, a snapshot or a volume is passed by the API to the machine that holds the thing, and a call that makes one to a machine the API picks; a list asks every machine and puts their answers together. What the machine answers comes back unchanged: that is what each of these calls lists. A project's secrets are kept by the API for all its machines, and answered in the same words. The API adds a few answers of its own to these calls, the same for each: Calls passed to a machine. The other calls (apps, projects, keys, spend limits, events, the account and its bill, the console) are the API's own.

Authentication

Every call but the console's sign-up and sign-in (/v1/auth/…) takes a credential, in Authorization: Bearer <credential>.

  • A project's key (ak_…). Make one in the console, on its API keys page, with the scopes and the expiry you choose, or with POST /v1/keys. The key is shown once, when it is made; DELETE /v1/keys/{id} revokes it at once. No key is 401 missing_api_key, a wrong one invalid_api_key, one past its expiry expired_api_key.
  • A token for one sandbox (st_…), from POST /v1/sandboxes/{id}/tokens: short-lived, with some of the scopes url, exec, files and tty. On a GET it may be the query parameter sandbox_token instead, for a browser, which cannot set headers on an EventSource or a WebSocket. The API passes a call made with a token to the machine of its sandbox, which checks the token: to a token every other sandbox is 404, and a call that takes a project's key is 403 needs_api_key.
  • The console's session. The console's own calls (/v1/me…, /v1/accounts/{id}…) take the cookie that POST /v1/auth/sign-in sets. With it, and X-Account and X-Project naming the account and the project, the console calls the rest of the API as a key of that project with every scope, within what the user's role in the account allows.

Scopes. A key allows some of seven scopes: read, write, exec, files, tty, url and admin (what each one opens). A key made without scopes has all of them but admin. Each call ends its description with the scope it takes ("Takes read."), and a key without that scope is 403 key_scope, whose message names it.

Projects

An account has one or more projects, and a key belongs to one of them. Everything a call makes with it is that project's, and a call sees only that project's sandboxes, snapshots, volumes, secrets, apps and the rest: another project's are not there (404). Names are unique within a project, for each kind of thing.

Ids begin with what they name: sbx-, exe- (a command), snap-, vol-, sshkey-. Wherever a path, a field or the sandbox_id filter takes the id of a sandbox, a snapshot, a volume or an SSH key, it takes its name as well (but in the host name of a link to a port).

Idempotency keys

Any POST may carry Idempotency-Key (1 to 255 characters). The same call again, with the same key and the same body, is answered as the first one was, with Idempotent-Replayed: true, and nothing is done twice. The same key with another body is 409 idempotency_key_reused; while the first call still runs, a second one waits up to 60 seconds, then is 409 idempotency_in_progress. An answer is kept for 24 hours; answers of 409 and of 5xx, and event streams, are not kept, and the call runs again. A command's key (…/run, …/exec) is kept with the command, for as long as the sandbox has it. A create sent again with its key goes to the machine the first one went to, and is given the size the first one was given, whatever the account's plan is by then.

Pagination

A list takes limit (1 to 1000; 100 when not given) and cursor, and answers {"data": […], "next_cursor": "…"}, newest first (the entries of a directory, and secrets, by name). next_cursor is null on the last page; give it as cursor for the next one. A cursor names a position, not a page: it stays good while things are made and deleted.

Errors

Every error has one shape:

{"error": {"type": "not_found", "code": "sandbox_not_found", "message": "no sandbox sbx-…",
           "param": null, "retryable": false, "request_id": "req-…", "docs_url": null}}

type sets the status: invalid_request 400, unauthenticated 401, payment_required 402, forbidden 403, not_found 404, conflict 409, too_large 413, too_many_requests 429, internal 500, bad_gateway 502, unavailable 503, timeout 504. code says which failure it is: each call lists its codes under each of its statuses. message says it in words for people; param names the field or the query parameter at fault; retryable says whether the same call again may succeed, and a Retry-After header says when, where that is known. A field or a query parameter the call does not take is refused (400 unknown_field, unknown_parameter), and the message lists what it takes. request_id is the call's id, in the answer's X-Request-Id header too: send an X-Request-Id of your own (1 to 64 letters, digits, ., _ and -) and it is used. A 500 says only that something failed: quote its request_id. docs_url, where an error has one, leads to its code on the errors page, which says what to do about the refusals that send you there: a plan's cap, a project's Drives and volumes, an account on hold, a locked user.

Event streams and terminals

A command's output can be read as a stream of events (text/event-stream): from POST /v1/run and POST /v1/sandboxes/{id}/run with stream: true (or Accept: text/event-stream), and from GET /v1/sandboxes/{id}/exec/{exec_id}/output. Each event has an event: line, for output an id: line (the position after the event's last byte, stdout and stderr counted together) and one data: line of JSON. A comment, : waiting, comes every 15 seconds while nothing happens. A reader that falls behind what the sandbox still keeps is told so with gap. To read on after a lost connection, ask …/exec/{exec_id}/output with Last-Event-ID (or from).

The events:

  • start: First event of a stream that started the command. Its data: {id, "object": "exec", sandbox_id, command}.
  • stdout: A piece of standard output. id is the position after its last byte. Its data: {text} or {base64}.
  • stderr: A piece of standard error. id is the position after its last byte. Its data: {text} or {base64}.
  • gap: Output is no longer kept: what the reader asked for, or what it was about to get. The stream goes on from available_from. Its data: {from, available_from}.
  • exit: Last event: the command has ended. id is the position after the last byte of its output. Its data: {id, "object": "exec", sandbox_id, command, tty, status, …} (as GET /v1/sandboxes/{id}/exec/{exec_id} answers it).
  • end: Last event of a stream asked for with follow=false while the command is still running. id is the position reached. Its data: {"status": "running", offset}.
  • error: Last event: the command was lost (the sandbox was restarted from its disk, restored or deleted), or the sandbox was moved to another node with its processes, where the command goes on: sandbox_moved (retryable), with to, epoch and offset, the id of the event before it; the same stream asked for again through the control plane with Last-Event-ID (or from) set to offset goes on there, missing nothing and repeating nothing. Its data is the error object of every other error. Its data: {error, …}, the error.

A terminal (GET /v1/sandboxes/{id}/exec/{exec_id}/tty) is a WebSocket. Binary messages are bytes: what is typed one way, what the terminal shows the other. Text messages are JSON:

  • {"type": "eof"}: Client to server, as a text message: the client sends no more. The guest half-closes its connection to the peer; what the peer still sends comes back.
  • {"type": "listening", path}: Server to client, the first message: where the socket is in the sandbox.
  • {"type": "reset"}: Server to client: every connection to the socket is gone (the sandbox went to sleep); the socket stays.
  • {"type": "resize", cols, rows}: Client to server, as a text message: the terminal has this size now. Out-of-range sizes are dropped without an answer.
  • {"type": "signal", …}: Client to server, as a text message: send the command's process group a signal.
  • {"type": "exit", status, exit_code, signal}: Server to client, as a text message: the command has ended. A close frame (1000) follows.
  • {"type": "error", error, …}: Server to client, as a text message: the command was lost (the sandbox was restarted, restored or deleted), or the sandbox was moved to another node with its processes, where the command goes on (sandbox_moved, retryable, with to, epoch and offset: join again through the control plane with from set to offset), or a key or a message of the client's was refused (spend_limit_reached, say). error is the error object of every other error. A close frame follows: 1012 with the reason sandbox_moved after sandbox_moved, 1000 otherwise. A key typed while the sandbox is being moved waits for the move's end: it goes in where the move failed.
  • {"type": "gap", from, available_from}: Server to client, as a text message: the client fell further behind than the sandbox keeps of a command's output (the last 16 MiB), and what the terminal shows next begins at available_from, not where it stood. Sent before what follows it, as a stream's gap event is. The bytes a terminal shows carry no position: a client that counts them, to join again with from after its connection was lost (the SSH gateway, whose sessions outlive a restart of the node's daemon), goes on counting from available_from.

Calls passed to a machine

What the machine that holds a thing answers is what each of these calls lists. The API answers some of them itself, before any machine is asked or in place of the machine's answer:

  • 400 invalid_json: Of POST /v1/sandboxes, /v1/run and /v1/volumes: the body is not a JSON object (no body is {}). Refused before any machine is asked, whether or not one is there.
  • 400 unknown_field: A create that gives project_address: the address of a sandbox on its project's network is the API's to give. Of a sandbox's drives, a field a mount does not have. A create or a change of a sandbox that is no Browser session that gives it a proxy: a proxy is a session's (POST /v1/browsers, PATCH /v1/browsers/{id}).
  • 400 unknown_region: A create whose region is not one of the regions.
  • 400 invalid_field: A volume made from a backup (from_backup) that also gives size_bytes, shared or from_backup_index (it has the size and the kind of the volume the backup was taken of), or a region other than the backup's. Of a sandbox's drives: no list, a path that is not absolute, a mode other than read_write (the read-only mount of a Drive's snapshot comes later).
  • 400 missing_field: A sandbox's create whose drives names a Drive without its drive or its path (param drives[i].drive, drives[i].path).
  • 400 reserved_metadata: A sandbox's create (POST /v1/sandboxes, /v1/run) or change (PATCH /v1/sandboxes/{id}) whose metadata names the key product (param metadata.product): what a sandbox is sold as (a Browser session) is the API's own record, and no metadata says it.
  • 400 unknown_parameter: A list that no machine answers (none is there, or none can be reached), which the API answers from what it last saw, given a query parameter the list does not take.
  • 402 account_in_debt: The account owes for what it stores past its plan. Every call is refused, before the key's scope is looked at, but reading the account, its bill, its usage and its backups, paying, making a volume from a backup, and (unless the API is run otherwise) listing, reading and deleting the sandboxes, snapshots and volumes it stores. The message says how much is owed and how to pay.
  • 403 key_scope: The key does not allow the scope the call takes; the message names it.
  • 403 account_held: The account is held for its payments: every call of its keys and of its sandboxes' tokens but GET /v1/account. The message says to write to support.
  • 403 spend_limit_reached: The project, or the sandbox, is at its spend limit: no sandbox, fork, one-shot run, volume (but one made from a backup) or snapshot is made, and a sandbox the limit froze is not woken.
  • 403 balance_used_up: The CPU time or the memory the account's plan includes is used up, and the account has no balance to pay for more: the same calls are refused.
  • 403 plan_size_exceeded: Larger than the account's plan lets a sandbox be: the limits asked for (param limits.vcpus, limits.memory_bytes, or limits for both), or the shape of the snapshot or template it is made from, forked from or rolled back to. A sandbox that names no size is made as large as the plan allows at most.
  • 403 plan_cap_reached: More than the account may have at once (param names which; GET /v1/account has them under caps): sandboxes awake, their vCPUs or their memory (of a create, a one-shot run, a fork, or a call that wakes a sandbox), sandboxes asleep, or sandboxes made in the last minute or hour (these are retryable, with Retry-After). A sleep and a delete are never refused.
  • 403 volume_limit_reached: Of POST /v1/volumes: one volume more, a larger one, or more in all than the plan lets a project keep (GET /v1/billing has the numbers).
  • 403 drive_limit_reached: Of a sandbox's snapshot that carries Drives: a sandbox made from it (POST /v1/sandboxes and POST /v1/run with snapshot), each copy of a fork of a sandbox that has Drives, and a sandbox taken back to it get a new Drive of each, and are refused before any machine is asked where those would take the project past the Drives its plan lets it keep (how many, how large each, how large together), as a fork through POST /v1/drives/{id}/fork is. param is snapshot of a create and a roll-back; the message says the plan's numbers, what the project has and what this would make.
  • 403 secret_limit_reached: Of PUT /v1/secrets/{name}: a secret more than the plan lets a project keep, a value larger than one may be (param value), or one that would give an app's instances more of the project's secrets than one sandbox may be given.
  • 403 proxy_not_on_plan: A change of a Browser session (PATCH /v1/sandboxes/{id}) that gives it a proxy on the free plan, which has none.
  • 403 account_share_reached: Something new of the account (a sandbox, a one-shot run, a fork's copies, a snapshot, a volume or Drive) would take it past its share of the data drive of the machine it would be on: one account holds at most a share of a machine's drive (a quarter unless the machine is set otherwise). The API puts what is new on a machine where the account has the room, and passes this on when none has.
  • 403 storage_quota_reached: Of an account on Free that keeps as much as Free lets it keep at once (15 GB of volume data: what its volumes hold, its snapshots and sleeping sandboxes keep): a new volume or snapshot is refused (param storage) until it keeps less, or is on Paid.
  • 404 backup_not_found: A volume made from a backup that the project does not have (param from_backup).
  • 404 drive_not_found: A sandbox's create whose drives names a Drive the project does not have (param drives[i].drive).
  • 404 snapshot_not_found: A sandbox's create whose drives mounts a snapshot of a Drive the project does not have (param drives[i].snapshot).
  • 409 not_on_one_machine: A sandbox and a volume it is to have, or a shared volume that the snapshot it is made from or rolled back to mounts, are on different machines. A volume no sandbox has had yet moves to the sandbox's machine instead. Of a sandbox's drives: the Drives it mounts, and the snapshots of Drives it mounts read-only, are of more than one region, or of another region than the create names (param region); a snapshot is read in the region its Drive was in when it was taken, whether or not the Drive was deleted since.
  • 409 snapshot_not_replicated: A sandbox is to be made from, or rolled back to, a snapshot on another machine than the one that took it (that one is away, or the volumes are elsewhere), and the snapshot is not in the object store yet: its last_replication_status says how its copy stands. param is snapshot.
  • 409 not_loadable: The machine the call goes to cannot make machines from the snapshot as it was published (another build of Firecracker, other settings of the devices, a larger shape, another size of disk); the message says what differs.
  • 409 backup_not_ready, backup_unusable: A volume made from a backup that is still being made, or that failed.
  • 409 too_many_drives, key_drive, duplicate_volume, drive_attached: Of a sandbox's create with drives: more than 8 Drives and volumes together (too_many_drives); a keyed instance's Drive (key_drive); one Drive named twice (duplicate_volume); a Drive another sandbox has, which stays where it is (drive_attached).
  • 409 not_copied, store_unfenced: Of a sandbox's create with drives: a Drive on another machine than the one the sandbox can be made on, where that machine copies nothing to an object store (not_copied), or copies to one that no move goes through (store_unfenced).
  • 409 managed_by_database: A sandbox's create (POST /v1/sandboxes, /v1/run), or a change of its mounts (PATCH /v1/sandboxes/{id} with volumes), that mounts a database's Drive read-write (param names it); a delete, a change or a restore of a sandbox that is a database's instance; any change of a volume that is a database's Drive. What a database is made of is changed through /v1/databases alone.
  • 409 managed_by_installation: The same of what an installation of a Managed Application is made of: a sandbox's create, or a change of its mounts, that mounts an installation's Drive read-write; a delete, a change or a restore of a sandbox that is an instance of an installation's app; any change of a volume that is an installation's Drive. What an installation is made of is changed through /v1/installations alone.
  • 409 checkpoints_unavailable: A sandbox with checkpoint on (its own setting, or a keyed instance's from its app) where no machine takes checkpoints, or where what it is made from is on a machine that does not; and a PATCH that turns them on, on a machine that does not. param is checkpoint. While every machine that takes them is away or full, the create is 503 no_capacity instead, retryable.
  • 429 quota_used_up: Of an account on Free that has used up today's quota (UTC) of the CPU time or the memory the call would use: a create, a one-shot run, a fork, or a call that would wake a sandbox is refused until 00:00 UTC, whatever the account holds (Retry-After says the seconds until then).
  • 502 fetch_failed: A sandbox made from, or rolled back to, a snapshot on another machine than the one that took it: that machine could not bring the snapshot from the object store. The message has its words.
  • 503 node_unavailable: The machine that holds the thing cannot be reached, or does not have the project's latest secrets yet: nothing is lost, and the same call will do once it is back (retryable).
  • 503 no_capacity: No machine has room for a new sandbox or volume (of a volume made from a backup: no machine of the backup's region makes them).
  • 503 moving: The sandbox is moving to another machine: every call for it until the move is over (retryable, Retry-After: 1).
  • 503 upgrading: The sandbox is a keyed instance its machine is moving over to another version of its app (POST /v1/apps/{app}/instances/{key}/upgrade): every call for it until the new version is up, or the instance is put back (retryable, Retry-After: 1).
  • 503 creation_cancelled, creation_cleanup_failed: The machine made the thing and the API could not record it: what the call made was deleted again (creation_cancelled), or not all of it could be (creation_cleanup_failed: the message lists what is left, which is billed until it is deleted).
  • 503 creation_replay_incomplete, creation_state_unavailable, creation_replay_record_failed: A create sent again with its Idempotency-Key, whose first answer the machine gives again: what that answer named is no longer all there (creation_replay_incomplete; another key makes it anew), the machine could not be asked (creation_state_unavailable, retryable), or it is all there and the API could not record it (creation_replay_record_failed).
  • 503 copy_behind, drive_not_brought, not_served_here, unavailable: Of a sandbox's drives, each brought first to the machine the sandbox is made on: the object store does not hold the Drive as it is yet (copy_behind); its machine did not let it go, or the other could not take it (drive_not_brought); no machine of the region that could take it keeps Drives (not_served_here); another call is bringing it (unavailable). Each is retryable but not_served_here.
  • 503 standby: This copy of the API is not the one that serves: the answer names the one that does (active). retryable, with Retry-After.

A sandbox, snapshot or volume whose machine cannot be reached is still listed and read, as the API last saw it, with status unavailable (of a sandbox, awake_because and sleep_tier are null). The creates take region (na, eu, ap), which the API reads itself and does not pass on; a sandbox's and a volume's region says where it is.

Aramak için yazın…

↑↓ gezinmek için↵ seçmek içinEsc kapatmak için