anything.solutions

REST API

Manage AnythingCloud infrastructure from agents, scripts, and CI.

The REST API gives an account full access to its AnythingCloud resources: domains, hosts, workers, buckets and objects, KV namespaces, TiniDB databases, instances, volumes, load balancers, public IPs, and billing. It can also read the account balance and recent transactions, start balance top-ups, and manage OAuth applications. Calls use a personal API key instead of a browser session, so they work from a server, a shell, or an automation agent without cookies or a CSRF token.

Authentication

Create a key in Settings → API keys. The full key is shown once, when it is created; only a hash is stored. Send it with every request:

Authorization: Bearer ac_live_your_key_here

X-API-Key: ac_live_your_key_here is accepted as an alternative. Session cookies are ignored by this API, so a browser cannot be tricked into calling it.

A key can expire after 1 day, 7 days, 30 days, 90 days, or 1 year, or it can never expire. Revoking a key stops it immediately. Creating a key requires the account password and, when enabled, a fresh second factor. Disabled, banned, or restricted accounts cannot use API keys.

OAuth application management is a separate capability. Enable Allow OAuth app management when creating a key only if that agent should be able to register or change apps that request member data. Keys without it can still use every cloud and wallet endpoint.

Base URL

https://anything.solutions/api/v1

Agents can fetch this page as OpenAPI JSON with Accept: application/json or from https://anything.solutions/docs/api.json.

All requests and responses use JSON. Send a JSON object as the request body, and always send Content-Type: application/json. Cloud endpoints require an active AnythingCloud account; create resources in the Cloud console first if needed. Wallet and OAuth application endpoints work without AnythingCloud.

Quick start

curl https://anything.solutions/api/v1/me \
  -H "Authorization: Bearer $ANYTHING_API_KEY"
{
  "user": {"id": 42, "username": "ada", "display_name": "Ada", "email": "[email protected]"},
  "key": {"id": 7, "name": "deploy agent", "prefix": "ac_live_AbCdEfGh", ...}
}

Conventions

TopicBehaviour
ShapeResource objects are returned directly. Lists return {"items": [...], "total": n}.
TimeUTC ISO 8601, for example 2026-11-02T16:00:00Z.
DeleteSuccessful deletes return 204 No Content. Instance deletion returns 202 because the host finishes asynchronously.
Errors{"ok": false, "error": "message", "code": "invalid_field", "status": 400} with a matching HTTP status.
Rate limit1200 requests per minute and 50,000 per day per key. A 429 response means slow down.
OwnershipEvery lookup is scoped to the key's account. Another account's resource is a 404.
RetriesSend Idempotency-Key on a JSON or bodyless write request. Replaying the same key and body returns the original response with Idempotent-Replayed: true; reusing it for a different request returns 409.

Domains

A domain is a root domain you prove ownership of with a TXT record. Routes and custom hosts belong to a domain; use Hosts to point a hostname at a bucket, worker, database, or instance.

MethodPathDescription
GET/domainsList root domains and their DNS records.
POST/domainsClaim a root domain. Body: {"hostname": "example.com"}.
GET/domains/{id}Domain details, DNS records, and routed hosts.
POST/domains/{id}/verifyCheck the TXT record and update the status.
DELETE/domains/{id}Delete the domain and every host routed from it.
curl -X POST https://anything.solutions/api/v1/domains \
  -H "Authorization: Bearer $ANYTHING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"hostname": "example.com"}'

The response includes the TXT record to add at _anythingcloud.example.com. Call verify after DNS updates; a mismatch returns the domain in its current state with last_error explaining what is missing.

Hosts

Hosts is one list across every hostname the account owns: automatic bucket endpoints, bucket routes, bucket custom domains, worker routes, database routes, and instance routes. Each entry reports its target, status, and whether it is enabled.

MethodPathDescription
GET/hostsList every hostname.
POST/hostsCreate a route (see body below).
GET/hosts/{hostname}One hostname.
PATCH/hosts/{hostname}Enable/disable, change cache rules, move a bucket host, or set WebSocket/exploit options.
DELETE/hosts/{hostname}Remove a route or custom host. Automatic bucket endpoints cannot be deleted.

To create a route, send the target and either a verified root_id with label, or a full hostname under a domain you own:

{
  "target_type": "bucket",
  "target_id": 3,
  "root_id": 1,
  "label": "assets"
}

target_type is bucket, worker, database, instance, or bucket_domain. An instance route also requires port; a worker route accepts mode (http or webhook). A bucket_domain body uses a full hostname and skips root_id/label.

PATCH accepts enabled, cache (an array of {"extension": "jpg", "ttl": 86400}), and for bucket routes or custom domains target_id, websockets, and block_exploits. Cache TTL values are 0 (never), 300, 3600, 86400, 604800, 2592000, and 31536000 seconds.

Workers

A worker is JavaScript with an address, versions, environment variables, and bindings. Creating one stores the first version; deploying new code stores another immutable version and the runtime picks it up.

MethodPathDescription
GET/workersList workers.
POST/workersCreate a worker. Body: name, optional slug, code, template, address_mode.
GET/workers/{id_or_slug}Worker details, routes, versions, env keys, bindings, and triggers.
PATCH/workers/{id_or_slug}Rename, change memory or timeout, toggle cache/logs/metrics, or pause.
DELETE/workers/{id_or_slug}Delete the worker and its bindings.
POST/workers/{id_or_slug}/deployDeploy code. Body: {"code": "...", "message": "..."}.
GET/workers/{id_or_slug}/envList environment variable names. Secret values are never returned.
PUT/workers/{id_or_slug}/env/{key}Set a variable. Body: {"value": "...", "secret": true}.
DELETE/workers/{id_or_slug}/env/{key}Remove a variable.
GET/workers/{id_or_slug}/versionsList version metadata.
GET/workers/{id_or_slug}/versions/{digest}/codeRead the code for one version.
POST/workers/{id_or_slug}/rollbackRoll back to the previous version.
POST/workers/{id_or_slug}/versions/{digest}/rollbackRoll back to a specific version.
GET/workers/{id_or_slug}/triggersList schedule and event triggers.
POST/workers/{id_or_slug}/triggersCreate a schedule or bucket-event trigger.
PATCH/workers/{id_or_slug}/triggers/{id}Enable or disable a trigger.
DELETE/workers/{id_or_slug}/triggers/{id}Delete a trigger.
POST/DELETE/workers/{id_or_slug}/kv-bindingsAdd or remove a KV binding.
POST/DELETE/workers/{id_or_slug}/database-bindingsAdd or remove a TiniDB binding.
POST/DELETE/workers/{id_or_slug}/bucket-bindingsAdd or remove a bucket binding.
GET/workers/{id_or_slug}/logsRecent logs. Query: limit, level, before_id.
DELETE/workers/{id_or_slug}/logsClear logs.
GET/workers/{id_or_slug}/analyticsUsage analytics. Query: range=24h|7d|30d.
POST/workers/{id_or_slug}/addressSet the automatic label or add a custom host.
DELETE/workers/{id_or_slug}/address/{route_id}Remove a custom address.

address_mode is builtin (default), none, or custom. A custom address also needs root_id and label, or a full hostname. template is used when code is omitted.

curl -X POST https://anything.solutions/api/v1/workers \
  -H "Authorization: Bearer $ANYTHING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "image resizer", "template": "hello", "address_mode": "builtin"}'

Buckets

Buckets are S3-compatible object stores. The API manages bucket settings and lifecycle; object uploads use the normal S3 API with the account's access key.

MethodPathDescription
GET/bucketsList buckets and their hosts.
POST/bucketsCreate a bucket. Body: name, optional public, billing_mode, quota_gb.
GET/buckets/{id_or_name}Bucket settings, endpoint, and custom hosts.
PATCH/buckets/{id_or_name}Rename, change visibility/versioning, or configure S3 Pages.
DELETE/buckets/{id_or_name}Delete an empty bucket.
GET/buckets/{id_or_name}/objectsList objects. Query: prefix, limit, cursor.
GET/PUT/DELETE/buckets/{id_or_name}/objects/{key}Read metadata, download a short-lived URL with ?download=true, upload raw bytes, or delete.
GET/buckets/{id_or_name}/objects/{key}/metadataObject metadata.
GET/buckets/{id_or_name}/objects/{key}/versionsList object versions.
POST/buckets/{id_or_name}/objects/{key}/versions/{version}/restoreRestore a version.
DELETE/buckets/{id_or_name}/objects/{key}/versions/{version}Delete a version.
POST/buckets/{id_or_name}/objects/delete-prefixDelete every object under a folder prefix.
POST/buckets/{id_or_name}/objects/moveMove or rename one object.
POST/buckets/{id_or_name}/cache/clearClear cached responses for the bucket.
GET/buckets/{id_or_name}/usageStorage, request, and traffic usage in USD.
POST/buckets/{id_or_name}/credentials/rotateRotate the account S3 key and return the new secret once.

billing_mode is payg (default) or plan. For plan, send quota_gb from the plan list. website on PATCH accepts a boolean or {"enabled": true, "index": "index.html", "error": "404.html"}.

Object uploads use the raw request body; the request Content-Type is stored as the object type. Use the account's normal S3 credentials for very large uploads and multipart transfers.

KV

A KV namespace stores text values by key, with optional metadata and expiry. Namespace slugs are unique across the platform.

MethodPathDescription
GET/kvList namespaces with usage.
POST/kvCreate a namespace. Body: name, optional slug.
GET/kv/{slug}Namespace details and usage.
DELETE/kv/{slug}Delete the namespace and all of its keys.
GET/kv/{slug}/keysList keys. Query: prefix, limit, cursor, preview.
DELETE/kv/{slug}/keysDelete every key in the namespace.
GET/kv/{slug}/keys/{key}Read a value and its metadata.
PUT/kv/{slug}/keys/{key}Write a value. Body: value (text), optional ttl, expiration, metadata.
DELETE/kv/{slug}/keys/{key}Delete one key.
POST/kv/{slug}/batchApply up to 200 get/put/delete operations.
GET/kv/{slug}/usageKey, byte, and operation usage in USD.
GET/kv/{slug}/snapshotExport every live entry in the namespace.
GET/kv/{slug}/changesRevision changes since since.
curl -X PUT "https://anything.solutions/api/v1/kv/feature-flags/keys/search" \
  -H "Authorization: Bearer $ANYTHING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"value": "on", "metadata": {"owner": "web"}}'

ttl is seconds from now, between 60 and 31,536,000. Send either ttl or expiration (a Unix timestamp), never both.

TiniDB

TiniDB databases are SQLite databases with a token-scoped HTTP SQL API. The REST API creates and deletes them, manages tokens, and helps bootstrap schemas.

MethodPathDescription
GET/databasesList databases.
POST/databasesCreate a database. Body: {"name": "Orders"}. The response includes the first token once.
GET/databases/{id_or_slug}Database, replicas, tokens, and routes.
DELETE/databases/{id_or_slug}Delete the database and revoke its tokens.
GET/databases/{id_or_slug}/tokensList token metadata (never the secret).
POST/databases/{id_or_slug}/tokensIssue a token. Body: {"name": "ci", "scope": "read"|"write"}.
DELETE/databases/{id_or_slug}/tokens/{token_id}Revoke a token.
POST/databases/{id_or_slug}/queryRun one statement. Body: {"sql": "SELECT ...", "params": []}.
GET/databases/{id_or_slug}/schemaList tables and columns.
POST/databases/{id_or_slug}/batchRun up to 100 statements in one batch.
POST/databases/{id_or_slug}/execExecute one write statement.
GET/databases/{id_or_slug}/usageRows, queries, storage, and cost in USD.
GET/databases/{id_or_slug}/limitsDatabase, storage, and row limits.
GET/databases/{id_or_slug}/backupsList backup status and size.
PATCH/databases/{id_or_slug}/tokens/{id}Rename a token.
curl -X POST "https://anything.solutions/api/v1/databases/orders/query" \
  -H "Authorization: Bearer $ANYTHING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sql": "CREATE TABLE IF NOT EXISTS orders (id INTEGER PRIMARY KEY, total INTEGER)"}'

For application traffic, use a TiniDB token with the database's own /db/v1/{slug}/query endpoint and keep the API key on the control plane. Query results use the same D1-shaped envelope as that endpoint.

Instances

Instances are full virtual machines cloned from an AnythingCloud image. Creating one requires an SSH key already saved in the account; use /instance-options to discover plans, images, and key ids.

MethodPathDescription
GET/instancesList instances.
POST/instancesCreate an instance. Body: name, plan, image, ssh_key_id, optional volume_ids, public_ip.
GET/instances/{id_or_public_id}Instance details and routes.
DELETE/instances/{id_or_public_id}Start asynchronous deletion.
POST/instances/{id_or_public_id}/startStart a stopped instance.
POST/instances/{id_or_public_id}/stopStop a running instance.
POST/instances/{id_or_public_id}/rebootReboot a running instance.
GET/instance-optionsPlans, available images, SSH keys, and current limits.
GET/instances/{id_or_public_id}/statusProvisioning progress and current status.
GET/POST/instances/{id_or_public_id}/snapshotsList or create snapshots.
DELETE/instances/{id_or_public_id}/snapshots/{name}Delete a snapshot.
POST/instances/{id_or_public_id}/snapshots/{name}/rollbackRoll back to a snapshot.
GET/POST/instances/{id_or_public_id}/firewallRead or change firewall settings and rules.
DELETE/instances/{id_or_public_id}/firewall/rules/{pos}Delete a firewall rule.
POST/instances/{id_or_public_id}/firewall/toggleEnable or disable the firewall.
GET/POST/volumesList or create volumes.
GET/DELETE/volumes/{id}Read or delete a volume.
POST/volumes/{id}/attach / detachAttach or detach a volume.
GET/POST/ssh-keysList or add SSH public keys.
DELETE/ssh-keys/{id}Delete an SSH key.
POST/ssh-keys/{id}/defaultMake an SSH key the default.
curl -X POST https://anything.solutions/api/v1/instances \
  -H "Authorization: Bearer $ANYTHING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "build-1", "plan": "small", "image": "ubuntu-26-04", "ssh_key_id": 4}'

Networking

Load balancers and public IPs are separate resources. Host traffic and cache rules are available on the existing host objects.

MethodPathDescription
GET/hosts/{hostname}/trafficTraffic analytics. Query: range=24h|7d|30d.
POST/hosts/{hostname}/verifyVerify a pending bucket custom domain.
GET/POST/load-balancersList or create load balancers.
GET/PATCH/DELETE/load-balancers/{reference}Read, configure, or delete a load balancer.
GET/POST/load-balancers/{reference}/backendsList or add backends.
DELETE/load-balancers/{reference}/backends/{id}Remove a backend.
GET/POST/load-balancers/{reference}/routesList or add hostnames.
DELETE/load-balancers/{reference}/routes/{id}Remove a hostname.
GET/POST/public-ips / /public-ips/reserveList or reserve public IPs.
POST/public-ips/{id}/bind / unbindBind or unbind an instance.
DELETE/public-ips/{id}Release a public IP.

Billing

Billing endpoints are read-only except for budget rules. Amounts are USD strings; internal billing units are never returned.

MethodPathDescription
GET/billingBalance, current month, expected month, and budget state.
GET/billing/usageMonthly spend by service. Query: range=6m.
GET/billing/limitsResource limits and current usage.
GET/POST/billing/budgetsList or set budget rules.
DELETE/billing/budgets/{id}Delete a budget rule.
GET/billing/activityRecent cloud activity. Query: limit, before_id.

Wallet

The wallet endpoints are credit-only. A key can read the account balance, start a top-up, and read recent transactions. It cannot spend the balance, request a payout, or move money to another member.

MethodPathDescription
GET/walletBalance and available top-up methods.
GET/wallet/transactionsRecent ledger entries. Query: limit, before_id.
GET/wallet/deposits/btcCurrent Bitcoin address and deposit state. ?refresh=true checks for new confirmations.
POST/wallet/deposits/btcCreate the persistent Bitcoin address once and return it.
POST/wallet/deposits/stripeCreate a hosted Stripe Checkout session. Body: {"amount_usd": "10.00"}.

Amounts and balances are USD decimal strings. Bitcoin state also includes the address URI, sats, confirmations, and the public exchange rate used for the last credit. The API never returns an upstream deposit reference or an internal error body.

curl -X POST https://anything.solutions/api/v1/wallet/deposits/stripe \
  -H "Authorization: Bearer $ANYTHING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount_usd": "25.00"}'

The response contains a checkout_url. Redirect the payer there; card details are entered on Stripe's hosted page and never reach this API. Credits are applied by the signed Stripe webhook, not by the checkout request. The success and cancel URLs are chosen by the server, so an API client cannot turn a payment into an open redirect.

OAuth applications

These endpoints manage applications registered for "Sign in with AnythingAuth". They require a key created with Allow OAuth app management enabled. The capability is off by default, so an infrastructure key cannot register apps or alter their return addresses.

MethodPathDescription
GET/appsList the account's applications.
POST/appsRegister an app. The client secret is returned once for confidential apps.
GET/apps/{public_id}App metadata, redirect URIs, scopes, and status.
PATCH/apps/{public_id}Change name, redirect URIs, scopes, or active state.
POST/apps/{public_id}/secretRotate the client secret. Body: {"client_secret": "current"}.
DELETE/apps/{public_id}Delete the app. Body: confirm_name, plus client_secret for confidential apps.
GET/apps/{public_id}/grantsList members who approved the app.
DELETE/apps/{public_id}/grants/{grant_id}Revoke one member's access.
GET/apps/{public_id}/tokensToken metadata, never raw tokens.
POST/apps/{public_id}/revoke-tokensRevoke all grants and tokens without changing the secret.
GET/apps/{public_id}/usageGrants, token counts, and storage usage.
GET/apps/{public_id}/storageList the owner's storage entries.
GET/PUT/DELETE/apps/{public_id}/storage/{key}Read, write, or delete one storage entry. Confidential apps require the client secret on writes.
curl -X POST https://anything.solutions/api/v1/apps \
  -H "Authorization: Bearer $ANYTHING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My App",
    "client_type": "confidential",
    "redirect_uris": ["https://example.com/oauth/callback"],
    "scopes": ["profile", "email"]
  }'

client_type is confidential (default) or public. Public apps use PKCE and do not receive a secret. Redirect URIs must be absolute https:// URLs; loopback http:// is allowed for local development. Unknown scopes are rejected, and an app can only use the scopes it registered.

App storage is per-member: the owner can manage their own entries through this API, and usage reports aggregate counts without exposing other members' values.

For a confidential app, the client secret is shown only in the create or rotate response. Changing its name, redirect URIs, scopes, or active state requires the current client_secret. A change also revokes every grant, token, and unexchanged authorization code, so members must approve the app again. Deleting requires both confirm_name and the current secret. This means a leaked API key alone cannot redirect an existing trusted app to an attacker-controlled callback.

Agent pattern

A safe, simple loop for an infrastructure agent:

  1. Call /me at startup to confirm the key and account.
  2. Read the current state with list endpoints before creating anything.
  3. Create or update resources with idempotent names and labels, then read the returned object instead of assuming success.
  4. Handle 409, 429, and 503 with a short backoff. Deletes and provisioning can finish asynchronously.
  5. Store the key in a secret manager. Never commit it or put it in a URL.