# GAP Cloud — Instructions for Agents GAP Cloud is an API-first backend for agent-built applications: projects, KV, objects, SQLite, functions, static sites, custom domains and realtime. Contract commerce, escrow, discovery and arbitration are archived and are not available on the Cloud server. ## Start here Create an identity with `POST /v1/identity`. The response includes an API `token`; keep it server-side and use `Authorization: Bearer `. Create a project with `POST /v1/cloud/projects`, then use its returned `project_id` in the examples below. Existing identities and project tokens remain valid. Never expose the owner bearer in browser code. ## Runtime services — use GAP as your backend If you need state or execution but do not want to operate infrastructure, create an owner-scoped cloud project with `POST /v1/cloud/projects`. The node provides: - KV: 64 KiB per value, 25 MiB per project; - objects: 1 MiB per object, 100 MiB per project; - private static hosting: Basic Auth mandatory, 3 MiB per file, 100 MiB total, 5,000 files, 5 retained versions, 20 requests/second and 1 GiB per rolling 30-day period; - SQLite: parameterized queries, one 100 MiB database per project; - JavaScript functions: 1 MiB per version, 100 MiB total, executed in the separately constrained sandbox container; - realtime free tier: 25 simultaneous connections, 25 active channels, messages up to 64 KiB, 30 messages/minute/connection, 300/minute/project, 24-hour retention and 25 MiB of persisted messages. An operator-funded credit balance can pay for controlled overages up to the hard safety limits documented below. All management routes require your normal agent bearer, and knowing a project identifier grants no access. Do not attempt `ATTACH`, `PRAGMA`, arbitrary network access or filesystem access: the runtime refuses them by design. Functions have a 30-second execution timeout. The 30-second budget covers the entire invocation after admission, including worker replays and waiting for storage/HTTP capabilities; it does not reset after each call. The queue wait described below is separate. Each invocation may dispatch up to **128 capability calls total**, including at most **32 HTTP calls**. SQL, KV, objects and realtime-token issuance share the total budget; failed calls also count, while replaying an already completed call does not. Limit checks happen before dispatching the excess operation. Prefer SQL batches and retry at the application level only when safe: earlier successful writes are not rolled back if a later call hits a limit or times out. The sandbox is allocated 1 CPU, 512 MiB and 256 PIDs, with at most 4 simultaneous invocations per project and 16 globally. A bounded queue holds 32 requests for at most 30 seconds. When it cannot accept an invocation, GAP returns HTTP `429` with `{"error":{"code":"sandbox_busy","message":"sandbox is busy"}}`; retry with exponential backoff and jitter rather than treating this as a malformed request. Set these once for every example below: ```bash export NODE=https://gap.geta.team export TOKEN=gat_your_agent_bearer ``` ### Projects — create and list ```bash # Create. Keep the returned project_id; it is used by every other route. curl -sX POST "$NODE/v1/cloud/projects" \ -H "Authorization: Bearer $TOKEN" # -> {"project_id":"prj_...","owner_did":"did:gap:...","status":"active",...} export PROJECT=prj_returned_above # List only the projects owned by this bearer. curl -s "$NODE/v1/cloud/projects" \ -H "Authorization: Bearer $TOKEN" # -> {"projects":[...]} ``` ### KV — put and get Values use standard base64. `expires_at` is an optional Unix timestamp. ```bash curl -sX PUT "$NODE/v1/cloud/projects/$PROJECT/kv/session-42" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"value_base64":"eyJzdGF0dXMiOiJhY3RpdmUifQ==","expires_at":1893456000}' # -> {"stored":true} curl -s "$NODE/v1/cloud/projects/$PROJECT/kv/session-42" \ -H "Authorization: Bearer $TOKEN" # -> {"found":true,"value_base64":"eyJzdGF0dXMiOiJhY3RpdmUifQ=="} # A missing or expired key returns {"found":false}. ``` ### Objects — put and get ```bash curl -sX PUT "$NODE/v1/cloud/projects/$PROJECT/objects/report.json" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"content_base64":"eyJvayI6dHJ1ZX0=","media_type":"application/json"}' # -> {"stored":true,"digest":"sha256:..."} curl -s "$NODE/v1/cloud/projects/$PROJECT/objects/report.json" \ -H "Authorization: Bearer $TOKEN" # -> {"found":true,"content_base64":"eyJvayI6dHJ1ZX0=", # "media_type":"application/json","digest":"sha256:..."} ``` ### Private static site — configure, deploy and activate Static hosting is intentionally private-only. There is no public mode: every request below `/sites/{project}/` requires the configured HTTP Basic credential. The owner bearer manages releases but is never used by visitors. Configure the site first. Passwords must contain 12–128 bytes; GAP stores an Argon2id hash and never returns the password or hash. On later updates, omit `password` to keep the existing credential. ```bash curl -sX PUT "$NODE/v1/cloud/projects/$PROJECT/site" \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"enabled":true,"entrypoint":"index.html","spa_fallback":true, "auth":{"mode":"basic","username":"visitor", "password":"replace-with-at-least-12-bytes"}}' # Read configuration, retained versions, active version, URL and exact quotas. curl -s "$NODE/v1/cloud/projects/$PROJECT/site" \ -H "Authorization: Bearer $TOKEN" ``` Create a draft version, upload each file as standard base64, then activate the completed version. MIME types come from a server-side extension allowlist; an upload cannot choose its own `Content-Type`. ```bash VERSION=$(curl -sX POST \ "$NODE/v1/cloud/projects/$PROJECT/site/versions" \ -H "Authorization: Bearer $TOKEN" | jq -r .version) curl -sX PUT \ "$NODE/v1/cloud/projects/$PROJECT/site/versions/$VERSION/files/index.html" \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"content_base64":"PCFkb2N0eXBlIGh0bWw+PGh0bWw+PGJvZHk+PGgxPkhlbGxvPC9oMT48L2JvZHk+PC9odG1sPg=="}' # Inspect the draft manifest or remove one draft file. curl -s "$NODE/v1/cloud/projects/$PROJECT/site/versions/$VERSION/files" \ -H "Authorization: Bearer $TOKEN" curl -sX DELETE \ "$NODE/v1/cloud/projects/$PROJECT/site/versions/$VERSION/files/obsolete.css" \ -H "Authorization: Bearer $TOKEN" curl -sX POST \ "$NODE/v1/cloud/projects/$PROJECT/site/versions/$VERSION/activate" \ -H "Authorization: Bearer $TOKEN" # The browser receives 401 + WWW-Authenticate until credentials are supplied. curl -u 'visitor:replace-with-at-least-12-bytes' \ "$NODE/sites/$PROJECT/" ``` An activated version is immutable and activation fails unless its entrypoint exists. Create the next version for an update; activation switches every path atomically. Delete only inactive versions: ```bash curl -sX DELETE \ "$NODE/v1/cloud/projects/$PROJECT/site/versions/1" \ -H "Authorization: Bearer $TOKEN" ``` Allowed assets are HTML, CSS, JavaScript modules, JSON, text, XML, SVG, common web images and web fonts. GAP rejects hidden/path-traversal names, executables, oversized files, invalid UTF-8 in text assets and forbidden control bytes. CSS, JS and MJS uploads have no content judgement: minified bundles and encoded content are accepted. Static uploads do not use the AI function judge. Other text assets retain the heuristic scan for excessive padding/obfuscation, embedded credentials, `` overrides and meta refreshes. Acceptance is not a security certification: never ship real secrets in browser assets. Server functions retain their separate static scan and AI security review. Every HTML response on the GAP-owned `/sites/{project}/` URL receives a non-removable "Hosted by GAP - private agent project" banner. Those responses use `private, no-store`, `nosniff`, `noindex, nofollow, noarchive`, no referrer, same-origin resource policy and a media-compatible CSP. Browser fetch/XHR connections may use any HTTPS origin, and WebSockets may use any WSS origin. Video/audio may use HTTPS or `blob:` URLs; embedded frames may use HTTPS, and workers may use same-origin or `blob:` URLs. This supports external players and HLS/MSE playback. Bundle player libraries (such as hls.js) as uploaded JavaScript files: external script CDNs, inline JavaScript and `eval` remain blocked. Plugins, embedding the GAP page inside another page, and cross-origin form submission also remain blocked. Images may use HTTPS, `data:` or `blob:` URLs; insecure HTTP resources remain blocked. `Referrer-Policy: no-referrer` prevents the private site URL and credentials from being sent as an image request referrer. Put configuration and application code in uploaded `.js` files rather than inline `