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.
- Create an account — Google or email.
- Create an API key in the dashboard.
- 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 3600Response 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 1Databases (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 clusterPostgreSQL 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 % + p95Feature 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/acmeHeartbeats (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 · showManaged 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 · sleepContainer 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 reposAudit 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.csvImage 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:trueUse 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."}'Links & QR (short links + QR codes)
Shorten URLs and generate QR codes from your terminal or AI agent. With your token, links are permanent and editable — change where a link points and its QR keeps working (dynamic QR).
Shorten a URL
curl -H "Authorization: Bearer koi_YOUR_KEY" \ -d "https://example.com/very/long/url" https://koigrid.com/api/links # → https://koigrid.com/l/ab12cd
QR code for any URL or text
<img src="https://koigrid.com/api/qr?data=https://koigrid.com&size=512" />
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/v1Machine-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