# StorkHost API > Agent-first hosting control plane. Grant credits to an account, deploy a metered workload on Kubernetes, and have it billed per pod-second until the balance reaches zero. All money is integer micro-credits (1 credit = $0.01 = 1_000_000 micro). Base URL: https://api.storkhost.cloud This platform is AGENT-FIRST: every capability below is plain HTTPS + JSON (no human, no browser, no KYC required) and the same surface is exposed as MCP tools. Machine-readable contract: OpenAPI at https://api.storkhost.cloud/v3/api-docs ## Onboard yourself: signup -> fund -> deploy 1. GET https://api.storkhost.cloud/v1/accounts/nonce ?address=0x — no auth. Returns a single-use nonce and the exact message to sign (EIP-191 personal_sign) with that address's key. 2. POST https://api.storkhost.cloud/v1/accounts {"address", "signature"} — no auth. Verifies the signature, mints your account and returns its FIRST API key: apiKey.key (sk_...) is shown exactly once — store it. One free account per wallet. From here on, send 'Authorization: Bearer sk_...' on every call. 3. GET https://api.storkhost.cloud/v1/capacity — no auth. Per payload type, whether a deploy would be accepted RIGHT NOW (available: true|false) plus retryAfterSeconds. Look at this BEFORE you top up for a deploy: if the type you want is not available, a create would be refused (nothing charged), so wait retryAfterSeconds and check again instead of paying first. 4. GET https://api.storkhost.cloud/v1/account/topup ?amountUsd=5 answers HTTP 402 with x402 version 1 payment requirements. Use the exact entry to sign a USDC EIP-3009 authorization with your account's bound wallet, then retry this same URL with X-PAYMENT and your API key. StorkHost submits the transfer and pays the gas. HTTP 200 confirms credit; HTTP 202 means pending: poll the returned status URL before starting another payment. 5. GET https://api.storkhost.cloud/v1/account/topup/exact/{id} poll an exact payment with the same account's API key. HTTP 202 means pending; HTTP 200 means confirmed with balanceMicro, ledger and the base64 JSON X-PAYMENT-RESPONSE header; HTTP 402 means the settlement failed and no credit was issued. Without an API key: GET https://api.storkhost.cloud/v1/x402/topup ?amountUsd=5 — no auth. The same exact top-up for x402 clients and directories that hold no API key: the account credited is the one whose signup wallet signs the payment. HTTP 402 carries x402 version 1 requirements in the body and the version 2 PaymentRequired in the PAYMENT-REQUIRED header; a wallet without an account is refused with 402 before anything is charged. Responses show the payment status only, never your balance. Without an API key: GET https://api.storkhost.cloud/v1/x402/topup/exact/{id} — no auth. Status of a key-less exact payment (the absolute pollUrl/Location you got): 202 pending, poll no faster than Retry-After; 200 confirmed (both receipt headers); 402 failed. 6. POST https://api.storkhost.cloud/v1/account/topup Alternative direct-transfer flow: first GET /v1/account/topup?paymentScheme=direct-transfer to open a deposit window, then {"txHash": "0x..."} — presents your mined Base transaction; it is verified on-chain and your balance is credited. Idempotent per transaction. 7. POST https://api.storkhost.cloud/v1/apps {"name", "payloadType", and exactly one of repoUrl | files | templateParams} — charges the build fee, builds the image and deploys a hardened, metered workload. Billing is per pod-second once RUNNING. If the cluster has no room for the payload type the answer is HTTP 503 with a Retry-After header and code capacity_unavailable: no app is created and NOTHING is charged — retry later, do not top up for it. 8. GET https://api.storkhost.cloud/v1/apps/{appId}/status watch it run: ready (true only while an instance is actually up — status stays RUNNING even if no pod could start; notReadyReason says why not), pod status, current burn rate (burnRateMicroPerSecond, micro-credits/s), remaining runway, and publicUrl for HTTP-exposed payload types. A scale-to-zero function with no instance up reports a current burn rate of 0 when idle time is not billed; burnRateWhileInstanceUpMicroPerSecond is its rate while serving. ## Payload types (generated from the live registry) Pass one of these as payloadType on POST /v1/apps: - cron — 116 micro-credits/pod-second (~$3.01/30-day month); requires a 'schedule' field (5-field cron expression, e.g. "*/5 * * * *") - function — 116 micro-credits/pod-second (~$3.01/30-day month); serves HTTP at a public https URL - hermes — 463 micro-credits/pod-second (~$12.00/30-day month); default egress allowlist: api.anthropic.com, api.openai.com, openrouter.ai, api.telegram.org; templateParams: model (required), instructions; supports an opt-in persistent state volume - mcp-server — 116 micro-credits/pod-second (~$3.01/30-day month); serves HTTP at a public https URL - one-shot — 116 micro-credits/pod-second (~$3.01/30-day month) - openclaw — 463 micro-credits/pod-second (~$12.00/30-day month); default egress allowlist: api.anthropic.com, api.openai.com, openrouter.ai, api.telegram.org; templateParams: model (required), agentName, instructions, telegramAllowFrom; supports an opt-in persistent state volume; the 1 GB size on an earlier OpenClaw release that knows Claude 5 (anthropic/claude-opus-5, claude-sonnet-5, claude-fable-5-1) and GPT-5.4 to 6.1 but not the Claude 5.5 family - openclaw-large — 926 micro-credits/pod-second (~$24.00/30-day month); default egress allowlist: api.anthropic.com, api.openai.com, openrouter.ai, api.telegram.org; templateParams: model (required), agentName, instructions, telegramAllowFrom; supports an opt-in persistent state volume; the newest OpenClaw release with 3 GB memory; needed for the Claude 5.5 model family - static-site — 30 micro-credits/pod-second (~$0.78/30-day month); serves HTTP at a public https URL; zero egress (initiates no outbound traffic) - telegram-bot — 116 micro-credits/pod-second (~$3.01/30-day month); default egress allowlist: api.telegram.org - web-service — 116 micro-credits/pod-second (~$3.01/30-day month); serves HTTP at a public https URL - webhook — 77 micro-credits/pod-second (~$2.00/30-day month); serves HTTP at a public https URL - worker — 116 micro-credits/pod-second (~$3.01/30-day month) ### Talk to your agent on Telegram Create a bot with BotFather and set its token as the env var TELEGRAM_BOT_TOKEN. Then name who may message the bot: - openclaw / openclaw-large: pass templateParams.telegramAllowFrom with your numeric Telegram user id (several ids comma-separated, up to 10). - hermes: set the env var TELEGRAM_ALLOWED_USERS to the same id. api.telegram.org is on these types' default egress allowlist. ### Default handler conventions (when you ship no Dockerfile) - function: main.py exposes handler(...). The runner is arity-tolerant — use `def handler(method, path, headers, body)` (headers=dict, body=bytes) OR `def handler(request)` (one object with .method/.path/.headers/.body, also request["body"]) OR a no-arg `def handler()` / `def main()`. Return a str/bytes (=> 200) or a (status, body) tuple. A dict is NOT auto-JSON'd — json.dumps it yourself. - mcp-server: main.py exposes plain top-level tool functions (no `handler`) — each public function becomes an MCP tool (name, docstring, string params) served at POST /mcp. - web-service: main.py must start an HTTP server bound to `$PORT` (env, default 8080) on 0.0.0.0 — the platform maps your public URL and the readiness probe onto that port. Bind any other/hardcoded port and the app still builds and goes RUNNING but never answers — a silent dead-but-billing workload. - every other type runs main.py (or your Dockerfile). Shipping a Dockerfile overrides the default for any type. ## Pricing (generated from the live configuration) All money is integer micro-credits: 1 credit = $0.01 = 1,000,000 micro; 1 USDC = $1.00 = 100000000 micro. - per-second compute: see the payload-type list above - one-time build fee per build: 5000000 micro ($0.05) - a build may run for at most 15 minutes; a build still running then is stopped and fails - refunded to your balance when a build fails on the platform side rather than in your build, up to 3 builds per account per 24 hours (the build logs say whether it was); at most 1 of those can be a build that hit the 15-minute limit or whose image could not be pushed - minimum top-up: 100000000 micro ($1.00) - persistent state (opt-in): 14000 micro/GiB-hour (~$0.10/GiB/30-day month) - gateway egress: 2000 micro/MiB (in+out) - max apps per account: 10 To estimate a quote: build fee + micro-credits-per-second x expected seconds (+ storage/GiB-hours if requested). Your live burn rate and runway are on GET /v1/apps/{appId}/status. Before you pay: GET /v1/capacity (no auth) says whether a deploy of each payload type would be accepted right now. Check it before topping up for a deploy — a refused deploy costs nothing, but there is no point funding one the platform cannot run yet. ## Funding (x402: USDC on Base) Standard x402 version 1 clients can pay with scheme exact on network base (chain ID 8453). GET /v1/account/topup?amountUsd=5 returns HTTP 402 with x402Version, error and accepts. The first entry is exact; its resource URL identifies the amount, maxAmountRequired is atomic USDC (6 decimals), and extra is {"name":"USD Coin","version":"2"}. The default amount is $5.00; amountUsd accepts cents only, from $1.00 through $1000.00. Always use the challenge's asset, payTo, resource and maxTimeoutSeconds. Retry the same amount URL with Authorization: Bearer sk_... and X-PAYMENT: base64-encoded JSON with x402Version=1, scheme=exact, network=base and payload containing signature and authorization (from, to, value, validAfter, validBefore, nonce). The payer must be the account's bound wallet; third-party payers and accounts without a bound wallet cannot use exact. StorkHost verifies the authorization and self-settles it on Base; no hosted facilitator is required and StorkHost pays transaction gas. HTTP 200 confirms credit with balanceMicro and ledger. Its X-PAYMENT-RESPONSE header is base64 JSON with success, transaction, network and payer. HTTP 202 means settlement is pending and no credit is confirmed: poll GET /v1/account/topup/exact/{id} at the returned pollUrl with the same API key, no faster than the Retry-After header; HTTP 402 from the poll means settlement failed. Retry or poll the same authorization rather than creating another payment while its outcome is pending. A failed receipt never credits the balance. x402 version 2 clients use the same URL: the 402 also carries the version 2 PaymentRequired object, base64 JSON in the PAYMENT-REQUIRED header (network eip155:8453, amount in atomic USDC, resource.url, the same extra). Retry with PAYMENT-SIGNATURE: base64 JSON with x402Version=2, accepted (the offered requirement, unchanged) and the same payload; the receipt is then in the PAYMENT-RESPONSE header. Send one payment header, not both. No API key at hand (or a stock x402 client that cannot send one)? GET /v1/x402/topup?amountUsd=5 is the same payment without auth, in either version: the account credited is the one whose signup wallet signs the authorization, so sign up first; an unknown wallet gets HTTP 402 before anything is charged. Discovery document for x402 directories: https://api.storkhost.cloud/openapi.json Existing clients can use the directTransfer sibling object, or request GET /v1/account/topup?paymentScheme=direct-transfer for the legacy challenge. Legacy fields also remain on accepts[0]; the accepts array contains only exact so standard clients can parse it. GET /v1/account/topup returns HTTP 402 whose body is the x402 challenge: asset (USDC contract), payTo (treasury address), minimum amount and your time-bounded deposit window. Pay on-chain, then POST /v1/account/topup {"txHash"} to be credited at 100000000 micro per USDC. The challenge is the source of truth for payment parameters — always fetch it first. ## REST API (generated from the running app) Auth: 'Authorization: Bearer sk_...' on everything except the signup pair, GET /v1/capacity and this manifest. Errors are a JSON envelope; over-limit calls get 429 + Retry-After. A deploy (create/start) the cluster has no room for gets 503 + Retry-After with code capacity_unavailable and retryAfterSeconds in the body — nothing is charged; GET /v1/capacity tells you in advance. The x402 group below needs no auth either: the payment itself names the account. ### Account - GET /v1/account — Get the calling account - POST /v1/account/checkout — Open a human hosted-checkout session (TryBit rail) - GET /v1/account/checkout/{id} — Get a hosted-checkout session - POST /v1/account/keys — Issue an API key - DELETE /v1/account/keys/{keyId} — Revoke an API key - GET /v1/account/ledger — List ledger entries - GET /v1/account/referral/payouts — List your referral payouts - POST /v1/account/referral/withdraw — Withdraw referral earnings to your bound wallet (USDC on Base) - GET /v1/account/referrals — Get this account's referral standing - GET /v1/account/topup — Get top-up payment requirements (x402 challenge) - POST /v1/account/topup — Submit a top-up payment (x402 settle) - GET /v1/account/topup/exact/{id} — Get an exact top-up settlement ### Admin - POST /v1/admin/accounts/{accountId}/block — Block (suspend) an account and stop its running apps - POST /v1/admin/accounts/{accountId}/grant — Manually grant credits to an account - POST /v1/admin/accounts/{accountId}/tier — Set an account's stored tier - POST /v1/admin/accounts/{accountId}/unblock — Unblock (reactivate) a suspended account - GET /v1/admin/activity — New signups and top-ups since the given cursors - GET /v1/admin/feedback — List feedback for triage - GET /v1/admin/feedback/{id} — Get one feedback item (admin) - PATCH /v1/admin/feedback/{id} — Triage a feedback item - GET /v1/admin/x402/pending — Inspect pending and review exact settlements using X-Admin-Token - POST /v1/admin/x402/{id}/fail — Close a REVIEW settlement as failed without credit using X-Admin-Token - POST /v1/admin/x402/{id}/resolve — Recheck an exact settlement without issuing credit using X-Admin-Token ### Apps - GET /v1/apps — List apps - POST /v1/apps — Create an app - DELETE /v1/apps/{appId} — Delete an app - GET /v1/apps/{appId} — Get an app - GET /v1/apps/{appId}/builds/{buildId} — Get a build - GET /v1/apps/{appId}/egress — Get app egress allowlist and usage - PUT /v1/apps/{appId}/env — Update app env vars - GET /v1/apps/{appId}/logs — Get app logs - POST /v1/apps/{appId}/restart — Restart an app - PUT /v1/apps/{appId}/spend-cap — Set or clear the app's spend cap - POST /v1/apps/{appId}/start — Start (resume) a stopped app - GET /v1/apps/{appId}/status — Get app runtime status - POST /v1/apps/{appId}/stop — Stop an app ### Auth - GET /v1/auth/api-keys — List API keys (human flow) - POST /v1/auth/api-keys — Issue an API key (human flow) - DELETE /v1/auth/api-keys/{keyId} — Revoke an API key (human flow) - GET /v1/auth/me — Get the current human account ### Capacity - GET /v1/capacity — Check whether a deploy would be accepted right now (public, per payload type) ### Discovery - GET /.well-known/llms.txt — Platform discovery manifest (llms.txt) - GET /llms.txt — Platform discovery manifest (llms.txt) ### Feedback - GET /v1/feedback — List your feedback - POST /v1/feedback — Submit feedback (bug report, feature request, or improvement) - GET /v1/feedback/pending-count — Count of feedback awaiting triage (public) - GET /v1/feedback/{id} — Get one of your feedback items ### Payments - POST /v1/payments/trybit/postback — TryBit payment-confirmation postback ### Signup - POST /v1/accounts — Create an account (agent self-signup) - GET /v1/accounts/nonce — Issue a signup nonce (challenge) ### Webhooks - DELETE /v1/apps/{appId}/webhook — Delete the app's webhook - GET /v1/apps/{appId}/webhook — Get the app's webhook - PUT /v1/apps/{appId}/webhook — Register or replace the app's webhook - GET /v1/apps/{appId}/webhook/deliveries — List recent webhook deliveries ### x402 - GET /v1/x402/topup — Key-less x402 top-up (payer wallet = account) - GET /v1/x402/topup/exact/{id} — Status of a key-less x402 top-up ## MCP POST https://api.storkhost.cloud/mcp — Streamable HTTP JSON-RPC 2.0 (initialize / tools/list / tools/call), same 'Authorization: Bearer sk_...' auth. 34 tools, one per REST operation above: delete_v1_account_keys_by_keyId, delete_v1_apps_by_appId, delete_v1_apps_by_appId_webhook, get_v1_account, get_v1_account_checkout_by_id, get_v1_account_ledger, get_v1_account_referral_payouts, get_v1_account_referrals, get_v1_account_topup, get_v1_account_topup_exact_by_id, get_v1_apps, get_v1_apps_by_appId, get_v1_apps_by_appId_builds_by_buildId, get_v1_apps_by_appId_egress, get_v1_apps_by_appId_logs, get_v1_apps_by_appId_status, get_v1_apps_by_appId_webhook, get_v1_apps_by_appId_webhook_deliveries, get_v1_capacity, get_v1_feedback, get_v1_feedback_by_id, post_v1_account_checkout, post_v1_account_keys, post_v1_account_referral_withdraw, post_v1_account_topup, post_v1_apps, post_v1_apps_by_appId_restart, post_v1_apps_by_appId_start, post_v1_apps_by_appId_stop, post_v1_feedback, post_v1_payments_trybit_postback, put_v1_apps_by_appId_env, put_v1_apps_by_appId_spend_cap, put_v1_apps_by_appId_webhook ## Links - OpenAPI JSON (full schemas): https://api.storkhost.cloud/v3/api-docs - Swagger UI: https://api.storkhost.cloud/swagger-ui.html - This manifest: https://api.storkhost.cloud/llms.txt (also https://api.storkhost.cloud/.well-known/llms.txt) — generated at runtime from the live endpoint, payload-type and MCP registries, so it always matches the deployed surface.