Documentation

Everything you need to use koigrid — by hand or with an AI agent.

Getting started

koigrid is API-first managed cloud. Create an account, generate an API key, and drive everything from your terminal or your AI agent.

  1. Create an account — Google or email.
  2. Create an API key in the dashboard.
  3. Call the REST API, or paste the agent prompt into Claude Code.

Authentication

Every /api/v1 endpoint authenticates with a Bearer token. Create one in Dashboard → API keys (it’s shown once).

curl https://koigrid.com/api/v1/me \
  -H "Authorization: Bearer koi_YOUR_KEY"

Mint scoped tokens by API (agent-native)

An agent can mint short-lived, scope-limited tokens by API — no dashboard needed. A token can never create another with more scopes than itself (no privilege escalation).

# mint a token that can only read apps + trigger deploys, expiring in 1h
curl -X POST https://koigrid.com/api/v1/tokens -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"ci deploy","scopes":["apps:read","apps:deploy"],"expiresInSeconds":3600}'
# → { "token": { "id":"…", "token":"koi_…" } }   (the secret is shown ONCE)

# list + revoke
curl https://koigrid.com/api/v1/tokens -H "Authorization: Bearer koi_YOUR_KEY"
curl -X DELETE https://koigrid.com/api/v1/tokens/<id> -H "Authorization: Bearer koi_YOUR_KEY"
# CLI: koigrid tokens create "ci deploy" --scopes apps:read,apps:deploy --expires 3600

Response shape

Success responses wrap the resource under its type key — they are not flat. A single resource comes as {"bucket":{…}}, {"database":{…}}, {"credential":{…}}, {"connection":{…}}; collections as {"buckets":[…]}. So read resp.credential.accessKey and resp.connection.uri — not resp.accessKey. Errors are {"error","detail"}. Tip: the CLI unwraps all of this for you.

Projects

A project groups related resources (an app + its database + cache + bucket + jobs) inside your organization — like Vercel projects or Google Cloud projects. Your org is the billing + team boundary; a project is the working scope. Every account has a Default project; switch or create projects from the selector at the top of the dashboard. Create a resource inside a project by passing projectId (default: your Default project).

# create a project and put resources in it
koigrid projects create prod
curl https://koigrid.com/api/v1/apps -H "Authorization: Bearer koi_YOUR_KEY" \
  -d '{"name":"web","projectId":"<project-id>"}'

Command-line interface (CLI)

Deploy and manage everything from your terminal, CI/CD, or your AI agent. The CLI is a thin client over the same API — install it with npm:

npm i -g koigrid
koigrid login
koigrid apps deploy web --image nginx:alpine --port 80
koigrid db create prod --replicas 1
koigrid apps ls --json   # machine-readable, for scripts or AI agents

Every command accepts --json for machine-readable output, and --token / KOIGRID_TOKEN for non-interactive auth. An AI agent (Claude Code, Cursor) can run koigrid commands directly — run `koigrid help --json` to introspect the full command set.

Apps (deploy by API)

Deploy a container or a git repo and get a live HTTPS URL — the Lambda/Railway alternative. Zero-downtime deploys, custom domains, env vars (encrypted), rollback, logs. Create the app, then trigger a deployment.

Create an app

curl -X POST https://koigrid.com/api/v1/apps \
  -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"my-app"}'

Deploy from a git repo (or an image)

curl -X POST https://koigrid.com/api/v1/apps/:id/deployments \
  -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sourceType":"git","repo":"https://github.com/you/app"}'
# → queued → live at https://<slug>.apps.koigrid.com (Dockerfile or nixpacks)

# Local code (private, no git/Docker needed):  koigrid apps deploy myapp --dir ./
# Private git repo:                            koigrid apps deploy myapp --repo <url> --repo-token <token>

Deploying Next.js? Set output:"standalone" in next.config and add a Dockerfile — koigrid builds it sandboxed. Nixpacks handles simpler apps with no Dockerfile. Note: deploy --dir excludes .git, so if your package.json "prepare" script runs husky/git, set HUSKY=0 (or guard it) so install does not fail.

Set env vars (encrypted, injected on redeploy)

curl -X POST https://koigrid.com/api/v1/apps/:id/env \
  -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"DATABASE_URL":"postgres://...","API_KEY":"..."}'

Resize (RAM/CPU per app, up to your plan max)

curl -X PUT https://koigrid.com/api/v1/apps/:id/resources \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"memoryMb":2048,"cpus":1}'   # RAM/CPU per app, up to your plan max
# CLI: koigrid apps resize <id> --memory 2048 --cpus 1

Databases (managed Postgres, HA)

Production Postgres with automatic failover, PgBouncer pooling and PITR backups — the RDS alternative. Create a cluster, get a TLS connection string, back up on demand or restore to a point in time.

Create a database (HA = leader + replica on paid plans)

curl -X POST https://koigrid.com/api/v1/databases \
  -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"prod","version":"16","replicas":1}'

Get the connection string — uri (writes → leader) and, on HA, readUri (reads → replicas)

curl https://koigrid.com/api/v1/databases/:id/connection \
  -H "Authorization: Bearer koi_YOUR_KEY"
# → { connection: { uri, host, port, database, username, caCert, sslVerifiedUri } }
#   port is dynamic per cluster; readUri exists only on HA plans (Free = no read replica)

Back up now / restore to a point in time

curl -X POST https://koigrid.com/api/v1/databases/:id/backups -H "Authorization: Bearer koi_YOUR_KEY"
curl -X POST https://koigrid.com/api/v1/databases/:id/restore \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"targetTime":"2026-07-03T10:00:00Z"}'   # PITR → new cluster

PostgreSQL versions & capabilities

PostgreSQL:
15, 16, 17 (default 17)
pgvector:
pre-installed — embeddings / búsqueda vectorial — CREATE EXTENSION vector; columnas vector(N). AI-native.
Extensions:
pg_trgm, unaccent, uuid-ossp, pgcrypto, citext, hstore, pg_stat_statements (CREATE EXTENSION)
Logical replication / CDC:
enabled — CREATE SUBSCRIPTION (in) + publications (out)
Pooling:
PgBouncer (incluido) · PITR · read replicas (HA)
TLS:
verificado (sslmode=verify-ca con CA propia — sin rejectUnauthorized:false)

Migrate your schema

Coming from RDS/Neon/Supabase? Point DATABASE_URL at your koigrid database and run your existing migrations unchanged — drizzle-kit migrate, prisma migrate deploy, etc. A real 99-table schema applied on the first try.

# Point your ORM at koigrid and run your existing migrations unchanged:
DATABASE_URL="$(koigrid db connection <id> --json | jq -r .connection.uri)" \
  npx drizzle-kit migrate        # or: prisma migrate deploy, atlas, etc.
# TLS verified out of the box: ssl:{ ca: caCert } on sslVerifiedUri (no rejectUnauthorized:false)

Cron jobs (scheduled tasks)

Run any container on a cron — the EventBridge alternative. Limits, logs, retries with backoff and gVisor isolation. Create the job; a tick runs it on schedule (or trigger it manually).

Create a scheduled job

curl -X POST https://koigrid.com/api/v1/jobs \
  -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"nightly","schedule":"0 3 * * *","image":"alpine:3","command":"echo hi","maxRetries":2}'

Trigger a run now / read the run logs

curl -X POST https://koigrid.com/api/v1/jobs/:id/trigger -H "Authorization: Bearer koi_YOUR_KEY"
curl https://koigrid.com/api/v1/jobs/:id/runs -H "Authorization: Bearer koi_YOUR_KEY"   # logs + exit code

Checks (Uptime & Synthetic Monitoring)

Create a check to watch an endpoint from the outside. koigrid pings it on a schedule and asserts status, latency and body, then alerts you (email + webhook) on down and recovery. Run-once to test instantly. The CloudWatch Synthetics replacement, driven by API.

# create a check: URL + assertions (status, latency, body) + alert webhook
curl -X POST https://koigrid.com/api/v1/checks \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"name":"api-health","target":"https://my.app/api/health","intervalSeconds":60,
       "assertions":[{"type":"status","value":"2xx"},{"type":"latency","value":800},{"type":"body_contains","value":"ok"}],
       "webhookUrl":"https://hooks.slack.com/…","alertAfter":2}'

# run it now (run-once) + see history/metrics
curl -X POST https://koigrid.com/api/v1/checks/:id/run  -H "Authorization: Bearer koi_YOUR_KEY"
curl https://koigrid.com/api/v1/checks/:id/runs         -H "Authorization: Bearer koi_YOUR_KEY"   # uptime % + p95

Feature Flags

Toggle features on/off and roll them out gradually by percentage, evaluated stably per user (the same user always sees the same variant). One evaluate call returns every flag as a boolean. The LaunchDarkly alternative, driven by API or your AI agent.

# create a flag, turn it on, and roll it out to 10%
curl -X POST https://koigrid.com/api/v1/flags \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"key":"checkout-v2","enabled":true,"rolloutPercent":10}'

# evaluate ALL flags for a user (stable per user) — the SDK call
curl -X POST https://koigrid.com/api/v1/flags/evaluate \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"context":"user-42"}'   # → {"flags":{"checkout-v2":true}}

Status Pages

A public status page for your users, generated from your Checks (each check = a component with its live status and uptime). Share one URL at /status/<slug>. The Atlassian Statuspage alternative.

# create a public status page — it shows this project's Checks (name + status + uptime)
curl -X POST https://koigrid.com/api/v1/status-pages \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"slug":"acme","name":"Acme Status"}'
# → public, no auth, at https://koigrid.com/status/acme

Heartbeats (Cron Monitoring)

A dead-man’s switch for your cron jobs: they ping a URL on success, and if koigrid does not hear from them within period+grace, it alerts you (email + webhook). The Healthchecks.io alternative, driven by API.

# create a heartbeat (dead-man's switch) — expects a ping every hour
curl -X POST https://koigrid.com/api/v1/heartbeats \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"name":"Nightly backup","periodSeconds":86400,"graceSeconds":600}'
# → returns pingUrl; add it to the end of your cron:
#   0 3 * * *  /backup.sh && curl -fsS https://koigrid.com/ping/<token>

Config & Secrets

Shared, encrypted configuration for the whole project: set a value once and every app or agent pulls it. Values are encrypted at rest and never shown in the dashboard or logs. The Doppler alternative.

# set a shared, encrypted value for the whole project
curl -X PUT https://koigrid.com/api/v1/config \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"key":"DATABASE_URL","value":"postgres://…"}'

# pull all config into your app (or: koigrid config pull > .env)
curl https://koigrid.com/api/v1/config/pull -H "Authorization: Bearer koi_YOUR_KEY"   # → {"config":{"DATABASE_URL":"…"}}

Web Analytics

Privacy-first traffic analytics: add one small script and see pageviews, unique visitors, top pages and referrers — no cookies, no personal data, no consent banner. The Plausible alternative, driven by API.

# create a site → returns a beacon snippet for your <head>
curl -X POST https://koigrid.com/api/v1/analytics/sites \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"name":"my-site.com"}'
# snippet:  <script defer src="https://koigrid.com/a.js" data-site="TOKEN"></script>

# read stats (no cookies, GDPR-friendly)
curl "https://koigrid.com/api/v1/analytics/sites/<id>/stats?days=30" -H "Authorization: Bearer koi_YOUR_KEY"

Error Tracking

Capture exceptions from your app and group them by fingerprint (message + top stack frame) so one bug is one line with a count. POST from your error handler with the ingest token. The Sentry alternative.

# get your ingest token (auto-created per project)
curl https://koigrid.com/api/v1/errors -H "Authorization: Bearer koi_YOUR_KEY"   # → { ingestToken, groups: [...] }

# capture an error from your app's error handler (public, by token)
curl -X POST https://koigrid.com/api/errors -H "Content-Type: application/json" \
  -d '{"token":"INGEST_TOKEN","message":"TypeError: x is undefined","stack":"at foo (a.js:1)","level":"error"}'

Firewall (WAF)

Allow/block rules by IP, CIDR, country, path prefix, method or user-agent. Add rules with the API; your edge/middleware calls POST /waf/evaluate per request to get an allow/block decision (first matching rule wins). The Cloudflare WAF alternative.

# add a block rule (blocks a whole country)
curl -X POST https://koigrid.com/api/v1/waf/rules -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"action":"block","matchType":"country","matchValue":"RU"}'

# your edge/middleware evaluates each request → { "action":"block", "ruleId":"…" }
curl -X POST https://koigrid.com/api/v1/waf/evaluate -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"ip":"1.2.3.4","country":"RU","path":"/api"}'

Webhooks

Subscribe a URL to your platform events. koigrid POSTs a signed JSON payload (verify the X-Koigrid-Signature HMAC-SHA256 header with your webhook secret) and retries with backoff (5 attempts, ~2h) if delivery fails. Subscribe to exact types, a domain prefix (app.*) or everything (*). Destinations are validated against SSRF. The Svix/Vercel webhooks alternative.

# 1) subscribe a URL to events (returns the signing secret ONCE)
curl -X POST https://koigrid.com/api/v1/webhooks -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://api.example.com/koi-hook","events":["app.*","db.failover"]}'
# → { "webhook": { "id":"…", "secret":"whsec_…" } }  ← save the secret

# 2) verify the signature on your endpoint (Node)
#   const expected = 'sha256=' + crypto.createHmac('sha256', SECRET).update(rawBody).digest('hex')
#   timingSafeEqual(expected, req.headers['x-koigrid-signature'])

# 3) inspect delivery history
curl https://koigrid.com/api/v1/webhooks/WEBHOOK_ID/deliveries -H "Authorization: Bearer koi_YOUR_KEY"

Log Drains

Forward your logs to an external sink. Create a drain (type http or datadog) with an optional set of headers (encrypted) and a source filter. koigrid buffers log records and the tick delivers new ones in batches; each drain keeps a cursor so a sink that is briefly down resumes without loss. Any app or agent can push its own structured logs to POST /logs. Destinations are validated against SSRF. The Vercel Log Drains alternative.

# 1) create a drain to an HTTP sink (extra headers are encrypted)
curl -X POST https://koigrid.com/api/v1/log-drains -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Better Stack","url":"https://in.logs.betterstack.com","headers":{"Authorization":"Bearer SOURCE_TOKEN"},"sources":["runtime","app"]}'
# Datadog: {"name":"DD","type":"datadog","headers":{"DD-API-KEY":"…"}}  (url defaults to DD intake)

# 2) push your own structured logs (any app or agent)
curl -X POST https://koigrid.com/api/v1/logs -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"records":[{"level":"error","message":"checkout failed","appId":"shop","source":"app"}]}'

# 3) query recent buffered logs
curl "https://koigrid.com/api/v1/logs?source=app&limit=50" -H "Authorization: Bearer koi_YOUR_KEY"

Spend Management

Set a monthly spend limit for your organization. GET /spend returns the current month spend, your limit and the percentage used; PUT /spend sets amountCents, the alert thresholds (percentages) and hardStop. As each threshold is crossed the owner is emailed and an event is emitted (so a webhook can forward it). With hardStop on, creating new paid resources (apps, databases, caches) is blocked once you reach the limit — reads and running services keep working. Spend is measured from your usage ledger. The Vercel Spend Management alternative.

# set a $50/month limit, warn at 80% and 100%, hard-stop new paid resources at 100%
curl -X PUT https://koigrid.com/api/v1/spend -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amountCents":5000,"thresholds":[80,100],"hardStop":true}'

# check where you stand this month
curl https://koigrid.com/api/v1/spend -H "Authorization: Bearer koi_YOUR_KEY"
# → { "spendCents":3120, "limit":{"amountCents":5000,…}, "pct":62, "over":false, "blocked":false }

Bot Management

Classify the user-agent (verified crawler / automated / likely human) and get an allow, challenge or block decision. Set the per-project policy with PUT /bots/policy (mode off|log|challenge|block, allowVerified). Your edge calls POST /bots/evaluate per request. For challenge mode, POST /bots/challenge issues a signed proof-of-work puzzle and POST /bots/verify checks the solution. Verified bots like Googlebot are allowlisted so your SEO never breaks. The Cloudflare Bot Management / Vercel BotID alternative.

# 1) set the policy (challenge automated traffic; verified crawlers always pass)
curl -X PUT https://koigrid.com/api/v1/bots/policy -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"mode":"challenge","allowVerified":true}'

# 2) your edge evaluates each request → { "action":"allow"|"challenge"|"block", "category":"…" }
curl -X POST https://koigrid.com/api/v1/bots/evaluate -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"userAgent":"python-requests/2.31","path":"/api"}'

# 3) challenge flow: issue → client solves the proof-of-work → verify
curl -X POST https://koigrid.com/api/v1/bots/challenge -H "Authorization: Bearer koi_YOUR_KEY"
# → { "challenge":"<token>", "difficulty":4 }   # find solution s.t. sha256(salt+solution) starts with N zeros
curl -X POST https://koigrid.com/api/v1/bots/verify -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"challenge":"<token>","solution":"<n>"}'  # → { "ok":true }

OpenTelemetry export

Export koigrid’s usage and cost metrics in native OTLP to any OpenTelemetry backend. PUT /otel sets the OTLP metrics endpoint and optional auth headers (stored encrypted); the endpoint is validated against SSRF. Every few minutes koigrid pushes your metrics as OTLP/JSON so they land in Grafana Cloud, Honeycomb, Datadog, Tempo or your own collector — open protocol, no lock-in. The Vercel OpenTelemetry alternative.

# point koigrid at your OTLP metrics endpoint (auth header stored encrypted)
curl -X PUT https://koigrid.com/api/v1/otel -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endpoint":"https://otlp.grafana.net/v1/metrics","headers":{"Authorization":"Basic <token>"}}'

# koigrid pushes OTLP/JSON every few minutes: koigrid.usage{metric=…} and koigrid.cost
curl https://koigrid.com/api/v1/otel -H "Authorization: Bearer koi_YOUR_KEY"
# → { "exporter":{"endpoint":"…","enabled":true,"lastExportAt":"…","lastError":null} }

DNS Management

Bring your own DNS provider: connect the zone you already own with POST /dns/zones (provider, domain, zoneId, apiToken — the token is stored encrypted). Then CRUD records under it: GET/POST /dns/zones/:id/records and PUT/DELETE /dns/zones/:id/records/:recordId, for A/AAAA/CNAME/TXT/MX/NS/CAA. Records are validated before they hit your provider. v1 supports Cloudflare (seam ready for more). Your zone stays in your account — no lock-in. The Vercel DNS / Cloudflare DNS alternative.

# 1) connect your zone (BYO provider — the token is stored encrypted)
curl -X POST https://koigrid.com/api/v1/dns/zones -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"provider":"cloudflare","domain":"example.com","zoneId":"<cf-zone-id>","apiToken":"<cf-token>"}'
# → { "zone": { "id":"…","domain":"example.com" } }

# 2) create a record
curl -X POST https://koigrid.com/api/v1/dns/zones/ZONE_ID/records -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"type":"A","name":"www","content":"1.2.3.4","proxied":false}'

# 3) list / delete
curl https://koigrid.com/api/v1/dns/zones/ZONE_ID/records -H "Authorization: Bearer koi_YOUR_KEY"
curl -X DELETE https://koigrid.com/api/v1/dns/zones/ZONE_ID/records/RECORD_ID -H "Authorization: Bearer koi_YOUR_KEY"

Queues

Durable message queue (SQS-like): send, receive with a visibility timeout, ack to delete, dead-letter after maxReceives. Scopes: queues:read / queues:write.

# 1) create a queue
curl -X POST https://koigrid.com/api/v1/queues -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"name":"tasks","visibilityTimeoutSec":30,"maxReceives":5}'
# → { "queue": { "id":"…","name":"tasks" } }

# 2) send a message (optional delaySeconds / dedupeId)
curl -X POST https://koigrid.com/api/v1/queues/QUEUE_ID/messages -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"body":"{\"job\":1}","delaySeconds":0}'

# 3) receive (claims + hides the message for visibilityTimeoutSec), then ack to delete
curl -X POST https://koigrid.com/api/v1/queues/QUEUE_ID/receive -H "Authorization: Bearer koi_YOUR_KEY" -d '{"max":1}'
# → { "messages": [ { "id":"…","body":"…","receiptHandle":"…:1" } ] }
curl -X POST https://koigrid.com/api/v1/queues/QUEUE_ID/ack -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"receiptHandle":"MSG_ID:1"}'

# CLI: koigrid queues create tasks · send · receive · ack · show

Managed WordPress

1-click WordPress hosting: a hosting account is an isolated OpenLiteSpeed container holding unlimited sites; each site gets its own database on a managed MariaDB Galera cluster. Scopes: wordpress:read / wordpress:write.

# 1) create a hosting account (isolated OLS container)
curl -X POST https://koigrid.com/api/v1/wordpress/accounts -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"name":"Acme","slug":"acme","planTier":"pro"}'
# → { "account": { "id":"…","slug":"acme" } }

# 2) 1-click install a WordPress site (wired to the managed DB, admin ready)
curl -X POST https://koigrid.com/api/v1/wordpress/accounts/ACCOUNT_ID/sites -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"slug":"blog","title":"Acme Blog","adminUser":"admin","adminEmail":"[email protected]"}'
# → { "site": { "id":"…","domainDefault":"blog.acme.sites.koigrid.com","adminPassword":"… (shown once)" } }

# 3) manage it by API with WP-CLI (AI-first; sanitized, allowlist, no shell)
curl -X POST https://koigrid.com/api/v1/wordpress/sites/SITE_ID/wp-cli -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"command":"plugin install woocommerce --activate"}'

# 4) back up the site (DB dump + files → S3)
curl -X POST https://koigrid.com/api/v1/wordpress/sites/SITE_ID/backups -H "Authorization: Bearer koi_YOUR_KEY"

# CLI: koigrid wp create acme --name "Acme" · wp install <acct> blog --title "Blog" · wp cli <site> plugin list · wp backup <site>

Workflows

Durable execution (Step-Functions-like): ordered steps, journaled outputs (a run survives crashes/redeploys), durable sleep + retries. Scopes: workflows:read / workflows:write.

# 1) define a workflow (ordered steps)
curl -X POST https://koigrid.com/api/v1/workflows -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"name":"order","steps":["charge","ship","notify"]}'

# 2) start a run
curl -X POST https://koigrid.com/api/v1/workflows/WF_ID/runs -H "Authorization: Bearer koi_YOUR_KEY" -d '{"input":"{\"orderId\":42}"}'
# → { "run": { "id":"RUN_ID","status":"running","currentStep":0 } }

# 3) worker loop: claim next step → run it → report result (completed steps never re-run)
curl -X POST https://koigrid.com/api/v1/workflows/WF_ID/runs/RUN_ID/next -H "Authorization: Bearer koi_YOUR_KEY"
# → { "step":"charge","context":{...},"input":"..." }
curl -X POST https://koigrid.com/api/v1/workflows/WF_ID/runs/RUN_ID/complete -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"step":"charge","output":{"chargeId":"ch_1"}}'
# durable sleep between steps: POST .../sleep {"seconds":3600}  · retry on failure: POST .../fail {"step":"...","error":"..."}

# CLI: koigrid workflows create order --steps charge,ship,notify · start · next · complete · sleep

Container Registry

Private OCI registry (ECR-like): docker push/pull to koigrid, images on koigrid Storage. Auth = Basic with a koigrid token carrying registry:read/registry:write. List repos: scope registry:read.

# 1) log in with a scoped koigrid token (password = the token)
docker login koigrid.com -u token -p koi_YOUR_TOKEN_WITH_registry_scope

# 2) tag + push
docker tag myapp:latest koigrid.com/myteam/myapp:v1
docker push koigrid.com/myteam/myapp:v1

# 3) pull from anywhere (any OCI client)
docker pull koigrid.com/myteam/myapp:v1

# list your repositories (management API / CLI)
curl https://koigrid.com/api/v1/registry/repositories -H "Authorization: Bearer koi_YOUR_KEY"
# → { "repositories": [ { "name":"myteam/myapp", "tags": 1 } ] }
# CLI: koigrid registry repos

Audit Log

Who did what — a curated, filterable record of every security/config change in your org, with the actor (user or API-token agent) and their source IP (CloudTrail-like). Owners/admins only, scope audit:read. Categories: auth, members, tokens, resources, deploy, network, security, billing, config.

# list audit entries (filter by category, action type, actor, date)
curl "https://koigrid.com/api/v1/audit?categories=members,security&sinceDays=30&limit=100" \
  -H "Authorization: Bearer koi_YOUR_KEY"
# → { "categories":[…], "entries":[ { "at":…, "action":"token.created", "label":"API token created",
#     "category":"tokens", "actorType":"user", "actor":"[email protected]", "ip":"1.2.3.4" }, … ] }

# export to CSV (same filters) for compliance / SIEM
curl "https://koigrid.com/api/v1/audit/export?sinceDays=90" -H "Authorization: Bearer koi_YOUR_KEY" -o audit.csv

# CLI
koigrid audit ls --category security --since 30
koigrid audit export --since 90 > audit.csv

Image Optimization

Resize and re-encode images on the fly. Allowlist your source hosts (anti-SSRF), then point an <img> at /img?token=…&url=…&w=…&fmt=webp — koigrid fetches, converts to WebP/AVIF, caches and serves. The Cloudinary/imgix/Vercel Images alternative.

# 1) allowlist your source hosts (anti-SSRF)
curl -X PUT https://koigrid.com/api/v1/images/config -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" -d '{"allowedHosts":["cdn.example.com","*.mybucket.s3.koigrid.com"]}'
# → { "publicToken":"…", "allowedHosts":[…], "imgBase":"https://koigrid.com/img" }

# 2) point your <img> at the optimized URL (public, cached)
<img src="https://koigrid.com/img?token=TOKEN&url=https://cdn.example.com/hero.jpg&w=800&fmt=webp" />

Sandboxes

Ephemeral compute: run a container image + command once and get the exit code and output back. One API call — ideal for AI agents running untrusted code, one-off tasks and build steps. Memory/time limited and isolated. The e2b/Modal/Vercel Sandboxes alternative.

# run a container image + command once → get exit code + logs (one API call)
curl -X POST https://koigrid.com/api/v1/sandboxes -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"image":"alpine:3.19","command":"echo hello from koigrid"}'
# → { "sandbox": { "status":"completed", "exitCode":0, "logs":"hello from koigrid", "durationMs": 812 } }

Speed Insights

Core Web Vitals (LCP, CLS, FCP, TTFB) from real visitors — reported at p75, the metric Google ranks by. Add the /v.js beacon next to your analytics tag (same site token) and read the numbers via the API. The Vercel Speed Insights alternative.

# add the vitals beacon next to your analytics tag (same site token)
<script defer src="https://koigrid.com/v.js" data-site="YOUR_SITE_TOKEN"></script>

# read Core Web Vitals (p75) from the API
curl https://koigrid.com/api/v1/speed-insights -H "Authorization: Bearer koi_YOUR_KEY"          # all sites
curl "https://koigrid.com/api/v1/speed-insights/<siteId>?days=30" -H "Authorization: Bearer koi_YOUR_KEY"

Cache / Redis (HA)

Managed Redis with master + replica + Sentinel quorum behind a stable endpoint — the ElastiCache alternative. Snapshots and restore included. Create the cache and get a rediss:// URL.

Create a Redis cache

curl -X POST https://koigrid.com/api/v1/redis \
  -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"sessions","version":"7"}'

Get the connection string / snapshot

curl https://koigrid.com/api/v1/redis/:id/connection -H "Authorization: Bearer koi_YOUR_KEY"
# → { connection: { uri: "rediss://:pass@rds-<slug>.dbs.koigrid.com:PORT" } }  (follows the master)

Storage (S3)

S3-compatible object storage. Create buckets, mint access keys scoped to only your buckets, and use any S3 tool.

Create a bucket

curl -X POST https://koigrid.com/api/v1/buckets \
  -H "Authorization: Bearer koi_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"backups"}'

Get an S3 access key (scoped to your buckets)

curl -X POST https://koigrid.com/api/v1/storage/keys \
  -H "Authorization: Bearer koi_YOUR_KEY"
# → { credential: { accessKey, secretKey, endpoint } }  (secret shown once)
# S3 client: use the bucket's bucketName (not its friendly name) + forcePathStyle:true

Use it with aws-cli

aws configure set aws_access_key_id  YOUR_ACCESS_KEY
aws configure set aws_secret_access_key YOUR_SECRET_KEY

aws s3 ls --endpoint-url https://s3.koigrid.com
aws s3 cp ./file.txt s3://YOUR_BUCKET/ --endpoint-url https://s3.koigrid.com

Or with rclone (~/.config/rclone/rclone.conf)

[koigrid]
type = s3
provider = Other
access_key_id = YOUR_ACCESS_KEY
secret_access_key = YOUR_SECRET_KEY
endpoint = https://s3.koigrid.com

# then: rclone ls koigrid:YOUR_BUCKET

Observability (events, metrics, alarms)

Query your event timeline, consumption and resource-health metrics, and set threshold alarms notified by email — the CloudWatch alternative. All by API.

Read the event timeline / metrics

curl "https://koigrid.com/api/v1/events?sinceHours=24" -H "Authorization: Bearer koi_YOUR_KEY"
curl "https://koigrid.com/api/v1/metrics?days=30"    -H "Authorization: Bearer koi_YOUR_KEY"

Create an alarm (on usage or resource health)

curl -X POST https://koigrid.com/api/v1/alarms \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"name":"redis-mem","resourceType":"redis","resourceId":"<id>","metric":"redis_used_memory_pct","comparator":"gt","threshold":80}'

Email (bring your own SMTP)

Transactional email through your own SMTP provider (Resend, SES, Postmark, your own server) — the SES alternative, no per-domain limits. Configure your provider once, then send.

Configure your SMTP provider (verified on save)

curl -X PUT https://koigrid.com/api/v1/email/config \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"smtp":"smtp://user:[email protected]:587","fromDefault":"Acme <[email protected]>"}'

Send an email

curl -X POST https://koigrid.com/api/v1/email/send \
  -H "Authorization: Bearer koi_YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"to":"[email protected]","subject":"Hello","text":"Sent through your own SMTP."}'

Share (upload → link)

Upload a file and get a shareable link in one step — from your terminal or your AI agent. Anonymous works (25 MB, 2h); add your token for 100 MB and 30-day links.

Anonymous (returns the URL as plain text)

curl -F [email protected] https://koigrid.com/api/share
# → https://koigrid.com/s/<id>

With your token (bigger files, permanent links)

curl -H "Authorization: Bearer koi_YOUR_KEY" \
  -F [email protected] https://koigrid.com/api/share

Resize & convert images on the fly (Cloudinary-style)

<img src="https://koigrid.com/s/<id>?w=400&format=webp" />

# params: w, h (px) · fit=cover|contain|inside · format=webp|avif|jpeg|png · q=1-100
# Served transformed, cached, bandwidth included. Manage your files in Dashboard → Files.

AI agents

koigrid is built to be driven by LLMs. Point your agent at /llms.txt and our API, or paste the prompt from the dashboard. Then ask it to create buckets, mint keys, etc.

https://koigrid.com/llms.txt

API reference

All endpoints require the header: Authorization: Bearer koi_YOUR_KEY

Base URL

https://koigrid.com/api/v1

Machine-readable API spec (OpenAPI 3.1) and LLM guide: https://koigrid.com/api/v1/openapi.json · /llms.txt

  • GET/me
  • GET/usage
  • GET/POST/tokens
  • DELETE/tokens/:id
  • GET/PUT/notifications/preferences
  • GET/POST/connect/grants
  • PATCH/DELETE/connect/grants/:id
  • POST/connect/token
  • POST/manifest
  • POST/manifest/plan
  • GET/POST/rewards
  • GET/rewards/lines
  • GET/rewards/referral
  • POST/rewards/redeem
  • POST/rewards/submissions/:id/review
  • GET/changelog
  • GET/POST/projects
  • DELETE/projects/:id
  • GET/POST/apps
  • GET/PATCH/DELETE/apps/:id
  • GET/POST/apps/:id/deployments
  • POST/apps/:id/source-upload
  • GET/apps/:id/logs
  • GET/PUT/apps/:id/scale
  • GET/PUT/apps/:id/resources
  • GET/PUT/apps/:id/autoscale
  • GET/PUT/apps/:id/scale-out
  • GET/POST/DELETE/apps/:id/env
  • GET/apps/:id/env/verify
  • GET/POST/DELETE/apps/:id/domains
  • POST/apps/:id/domains/verify
  • GET/POST/apps/:id/volumes
  • DELETE/apps/:id/volumes/:volId
  • GET/POST/apps/:id/volumes/:volId/backups
  • POST/apps/:id/volumes/:volId/backups/:backupId/restore
  • GET/PUT/apps/:id/cdn
  • GET/PUT/apps/:id/github
  • POST/apps/:id/rollback
  • POST/apps/:id/pause
  • POST/apps/:id/resume
  • POST/apps/:id/migrate
  • GET/POST/apps/:id/previews
  • GET/POST/apps/:id/rules
  • PATCH/DELETE/apps/:id/rules/:ruleId
  • POST/apps/:id/restore
  • GET/POST/databases
  • GET/PATCH/DELETE/databases/:id
  • GET/databases/:id/connection
  • GET/POST/databases/:id/backups
  • POST/databases/:id/restore
  • GET/POST/databases/:id/restore-dump
  • POST/databases/:id/fix-ownership
  • POST/databases/:id/restore-dump/upload-url
  • GET/databases/:id/restore-dump/:jobId
  • GET/databases/:id/metrics
  • GET/databases/:id/logs
  • GET/POST/databases/:id/extensions
  • GET/POST/databases/:id/query
  • GET/POST/databases/:id/replicas
  • GET/POST/DELETE/databases/:id/publications
  • POST/databases/:id/apply-config
  • GET/POST/DELETE/databases/:id/subscriptions
  • GET/POST/databases/:id/branches
  • GET/PATCH/DELETE/databases/:id/branches/:branchId
  • POST/databases/:id/branches/:branchId/reset
  • GET/POST/databases/:id/roles
  • PATCH/DELETE/databases/:id/roles/:roleName
  • GET/PUT/databases/:id/rotation
  • POST/databases/:id/rotation/rotate
  • POST/databases/:id/rotation/migrate
  • POST/databases/:id/rpc/:fn
  • GET/POST/PATCH/DELETE/databases/:id/data/:table
  • GET/POST/redis
  • GET/PATCH/DELETE/redis/:id
  • GET/redis/:id/connection
  • GET/POST/redis/:id/backups
  • POST/redis/:id/apply-config
  • POST/redis/:id/restore
  • GET/redis/:id/metrics
  • GET/POST/buckets
  • DELETE/buckets/:id
  • GET/POST/buckets/:id/versions
  • GET/DELETE/buckets/:id/objects
  • POST/buckets/:id/objects/upload-url
  • GET/buckets/:id/objects/download-url
  • GET/POST/storage/keys
  • DELETE/storage/keys/:id
  • GET/POST/jobs
  • GET/PATCH/DELETE/jobs/:id
  • GET/jobs/:id/runs
  • POST/jobs/:id/trigger
  • GET/events
  • GET/metrics
  • GET/POST/alarms
  • DELETE/alarms/:id
  • GET/POST/anomalies
  • DELETE/anomalies/:id
  • POST/email/send
  • GET/email/messages
  • GET/PUT/DELETE/email/config
  • GET/POST/checks
  • GET/PATCH/DELETE/checks/:id
  • POST/checks/:id/run
  • GET/checks/:id/runs
  • GET/POST/webhooks
  • PATCH/DELETE/webhooks/:id
  • GET/webhooks/:id/deliveries
  • GET/POST/log-drains
  • PATCH/DELETE/log-drains/:id
  • GET/POST/logs
  • GET/PUT/DELETE/spend
  • GET/PUT/bots/policy
  • POST/bots/evaluate
  • POST/bots/challenge
  • POST/bots/verify
  • GET/PUT/DELETE/otel
  • GET/POST/dns/zones
  • DELETE/dns/zones/:id
  • GET/POST/dns/zones/:id/records
  • PUT/DELETE/dns/zones/:id/records/:recordId
  • GET/POST/queues
  • GET/PATCH/DELETE/queues/:id
  • POST/queues/:id/messages
  • POST/queues/:id/receive
  • POST/queues/:id/ack
  • GET/POST/workflows
  • GET/PATCH/DELETE/workflows/:id
  • GET/POST/workflows/:id/runs
  • GET/workflows/:id/runs/:runId
  • POST/workflows/:id/runs/:runId/next
  • POST/workflows/:id/runs/:runId/complete
  • POST/workflows/:id/runs/:runId/fail
  • POST/workflows/:id/runs/:runId/sleep
  • GET/POST/wordpress/accounts
  • GET/DELETE/wordpress/accounts/:id
  • GET/POST/wordpress/accounts/:id/sites
  • GET/DELETE/wordpress/sites/:id
  • POST/wordpress/sites/:id/wp-cli
  • GET/POST/wordpress/sites/:id/backups
  • GET/POST/wordpress/sites/:id/domains
  • POST/PATCH/DELETE/wordpress/domains/:id
  • GET/PUT/apps/:id/protection
  • GET/PUT/apps/:id/retention
  • PUT/apps/:id/registry
  • POST/apps/:id/loadtest
  • POST/apps/:id/protection/evaluate
  • GET/POST/apps/:id/deploy-hooks
  • DELETE/apps/:id/deploy-hooks/:hookId
  • GET/registry/repositories
  • GET/registry/repositories/:name/tags
  • DELETE/registry/repositories/:name/tags/:tag
  • POST/databases/:id/pause
  • POST/databases/:id/resume
  • POST/registry/gc
  • GET/audit
  • GET/audit/export
  • GET/POST/members
  • GET/PUT/members/two-factor
  • PATCH/DELETE/members/:userId
  • DELETE/members/invitations/:id
  • GET/POST/flags
  • GET/PATCH/DELETE/flags/:key
  • POST/flags/evaluate
  • GET/POST/status-pages
  • GET/PATCH/DELETE/status-pages/:id
  • GET/POST/status-pages/:id/incidents
  • PATCH/status-pages/:id/incidents/:incidentId
  • GET/POST/heartbeats
  • GET/PATCH/DELETE/heartbeats/:id
  • GET/PUT/config
  • GET/config/pull
  • DELETE/config/:key
  • GET/POST/analytics/sites
  • GET/DELETE/analytics/sites/:id
  • GET/analytics/sites/:id/stats
  • GET/errors
  • PATCH/DELETE/errors/groups/:id
  • GET/speed-insights
  • GET/speed-insights/:id
  • GET/POST/sandboxes
  • GET/sandboxes/:id
  • GET/PUT/images/config
  • GET/images/usage
  • GET/POST/waf/rules
  • PATCH/DELETE/waf/rules/:id
  • POST/waf/evaluate