From 4ed2f4eb6db27a1edd58146b4e12ba5acf501443 Mon Sep 17 00:00:00 2001 From: Manas Srivastava Date: Wed, 1 Jul 2026 10:00:00 +0530 Subject: [PATCH 1/8] docs(claim): claiming moves to Free tier (24h TTL), not hobby-by-default docs/claim.md said claiming moves resources to 'hobby by default ($9/mo)', contradicting policy + home.md/pricing.md/llms.txt: claiming gives a Free-tier account (24h TTL, same limits as anonymous), NOT an automatic paid plan. Resources keep expiring at 24h until the user upgrades. Reframed to the canonical pricing.md/llms.txt copy + the no-trial/pay-from-day-one policy. Co-Authored-By: Claude Fable 5 --- docs/claim.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/claim.md b/docs/claim.md index 1bc681d..ca845b5 100644 --- a/docs/claim.md +++ b/docs/claim.md @@ -23,6 +23,8 @@ Click the magic link to set a session cookie. Every resource attached to your fingerprint transfers to your team atomically; the connection URLs don't change so any already-running code keeps working. -Claimed resources move to your team's tier (hobby by default — $9/mo). There -is no separate trial period on paid tiers — **the 24-hour anonymous slice -is the trial**. +Claimed resources move to your team's **Free tier** (24h TTL, same limits as +anonymous) — claiming gives you an account, not durability. Resources keep +expiring at 24 hours until you upgrade to a paid tier (Hobby $9/mo or above) +in the dashboard. Paid tiers bill from day one — there is no separate trial +period. From 9ed7f677c807b44ad125e8833c13c22acb385e7f Mon Sep 17 00:00:00 2001 From: Manas Srivastava Date: Sun, 21 Jun 2026 10:00:00 +0530 Subject: [PATCH 2/8] docs(leads): document POST /api/v1/leads enterprise contact endpoint Surface the new leads endpoint in llms.txt so agents know to call it when a user needs capacity beyond Pro (dedicated infra, SAML, compliance) rather than asking the agent to invent a path. Includes field validation rules (email required, name/company/use_case lengths, error codes). Co-Authored-By: Claude Sonnet 4.6 --- llms.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/llms.txt b/llms.txt index 40ac316..e6ae5fb 100644 --- a/llms.txt +++ b/llms.txt @@ -56,6 +56,7 @@ Pick a descriptive name per resource (e.g. `"prod-db"`, `"sessions-cache"`, `"ev - `POST /auth/github` — body-flow GitHub login (server-to-server; not used by the dashboard). - `GET /auth/me` — current user/team. Requires session JWT. - `POST /auth/logout` — `jti`-revocation via Redis set. Requires session JWT. +- **`POST /api/v1/leads`** — Enterprise contact / interest form. Body: `{"email": "you@corp.com", "name": "Alice", "company": "Acme", "use_case": "We need unlimited Postgres..."}`. Only `email` is required (validated via `mail.ParseAddress`; 254-char cap; returns `400 invalid_email_format` on bad input). Optional fields: `name` (≤128 chars, `400 invalid_name` if over), `company` (≤128 chars, `400 invalid_company`), `use_case` (≤1024 chars, `400 invalid_use_case`). Returns `201 {ok: true, id: ""}` on success. No authentication required. Authenticated callers have the lead automatically linked to their team. Use this when a user needs capacity beyond the Pro tier (e.g. dedicated infra, SAML, compliance) — it reaches the instanode.dev team directly. The MCP tool `create_lead` wraps this endpoint. - **`POST /api/v1/billing/promotion/validate`** — Validate a promo code without applying it. Body: `{"code": "EARLYBIRD"}`. Returns `{ok, discount_percent, discount_amount_inr, message}` for valid codes. Promo codes only DISCOUNT at checkout once a corresponding Razorpay Offer exists in the dashboard — validate-result `ok=true` is necessary but not sufficient until then. ## Anonymous tier limits (free, 24-hour TTL) From 9cb691ef45557c91fca42ab2dcbee099e9080af1 Mon Sep 17 00:00:00 2001 From: Manas Srivastava Date: Tue, 23 Jun 2026 11:00:00 +0530 Subject: [PATCH 3/8] docs(env): document env scoping parameter for all provisioning endpoints Agents omitting env were silently landing resources in 'development' without knowing it. Surface the default and semantics explicitly so an agent building a production stack passes env='production' rather than leaving the dashboard column empty. Co-Authored-By: Claude Sonnet 4.6 --- llms.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/llms.txt b/llms.txt index e6ae5fb..1e199bf 100644 --- a/llms.txt +++ b/llms.txt @@ -119,6 +119,7 @@ on `/api/v1/capabilities` for agent introspection. 5. **Internal vs public URL** — when the calling code itself runs *inside* a `/deploy/new` container, prefer `internal_url` (cluster-internal hostname). For everything else, use `connection_url` (public). 6. **Fingerprint dedup** — anonymous callers get rate-limited to 5 provisions/day/IP-subnet. The 6th call returns the existing token. Don't expect 6 different DBs from 6 calls on the same IP. 7. **Idempotency is on by default** — every POST that creates a resource (db/cache/nosql/queue/storage/webhook/vector/deploy/stacks/backup/restore/billing-checkout/team-invite/api-keys/twin/promote/admin-promo) is idempotent. Two layered guards: (a) the standard `Idempotency-Key` request header, Stripe-shape, 24h TTL — pass a UUID per logical retry; (b) when no header is sent, the server synthesises a fingerprint from `sha256(scope, route, canonical-body)` and dedups identical retries inside a 120s window (covers double-clicks, mobile double-taps, agent retries on transient 5xx). Replays carry `X-Idempotent-Replay: true`. Every create response sets `X-Idempotency-Source: explicit | fingerprint | miss` so callers can branch on which path matched. Use the explicit header when you need exactly-once guarantees beyond 120s. +9. **`env` tags resources to an environment scope.** Every provisioning endpoint (`/db/new`, `/vector/new`, `/cache/new`, `/nosql/new`, `/queue/new`, `/storage/new`, `/webhook/new`, `/stacks/new`) accepts an optional `"env"` string field (`"development"` or `"production"`). Default when omitted: `"development"`. The resolved value is echoed back in the response as `"env"`. Environment is metadata only — it does not change isolation, limits, or TTL. Use `"env":"production"` for resources backing a live user-facing app so the dashboard can show them in the right column. An agent should pass `env` so the user's dashboard reflects the deployment intent, but must never reject or retry a request solely because `env` is missing from the response. 8. **Don't send fields the endpoint doesn't define** — there are no `region`, `size`, `plan`, or similar knobs on the provisioning bodies (the only required field is `name`; a few endpoints take documented optionals like `/deploy/new`'s `port`/`env`/`env_vars`). Unrecognized top-level JSON keys are accepted (not rejected) but **ignored**, and the success response echoes them back in an `ignored_fields` array (sorted). So if you sent `{"name":"db","region":"nyc3","size":"large"}` you'll get `"ignored_fields":["region","size"]` — a signal that those keys did nothing. Treat a non-empty `ignored_fields` as a lint warning that your request shape drifted from the contract; don't keep sending fields it lists. ## Text-only routes for LLM consumption From 3090a674c7b03b8f1d98b57e25eacca0150df623 Mon Sep 17 00:00:00 2001 From: Manas Srivastava Date: Sun, 28 Jun 2026 10:30:00 +0530 Subject: [PATCH 4/8] docs(sdk): add Go SDK section with typed API examples Go agents were using curl in generated code instead of the typed SDK. Surfacing the SDK in llms.txt gives LLMs an ergonomic first choice: typed structs, INSTANT_TOKEN resolution, *APIError with AgentAction. Includes CreateLead since agents hitting Enterprise limits need a type-safe way to escalate to sales without hand-rolling JSON. Co-Authored-By: Claude Sonnet 4.6 --- llms.txt | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/llms.txt b/llms.txt index 1e199bf..4c1888a 100644 --- a/llms.txt +++ b/llms.txt @@ -173,6 +173,37 @@ The instanode.dev MCP server wraps the API as tools, so an MCP-capable agent nev This means an agent can run the entire arc — provision → deploy → set secrets → presign storage → debug a failure → rotate credentials → pause/resume — without ever leaving the MCP toolset. Every `create_*` tool surfaces the API's `note` + `upgrade` (claim URL) fields so the agent can show the user how to keep a resource past the anonymous TTL. +## Go SDK (`github.com/InstaNode-dev/sdk-go`) + +The instanode.dev Go SDK wraps the full API surface as typed method calls so Go agents never have to hand-roll HTTP. It mirrors the MCP server's coverage — provision, operate, inspect. + +```go +import instanode "github.com/InstaNode-dev/sdk-go" + +c := instanode.NewClient(instanode.WithToken(os.Getenv("INSTANT_TOKEN"))) + +// Provision +db, err := c.CreatePostgres(ctx, instanode.CreateParams{Name: "prod-db", Env: "production"}) +// db.ConnectionURL — ready to use + +// Deploy +deploy, err := c.CreateDeploy(ctx, instanode.DeployParams{ + Name: "my-api", Tarball: tarBytes, Port: 8080, Env: "production", +}) + +// Operate +_, err = c.SetVaultKey(ctx, instanode.VaultKeyParams{Env: "production", Key: "DB_URL", Value: db.ConnectionURL}) +_, err = c.UpdateDeployEnv(ctx, instanode.EnvPatchParams{ID: deploy.ID, EnvVars: map[string]string{"RELOAD": "1"}}) + +// Inspect +events, err := c.GetDeploymentEvents(ctx, deploy.ID) + +// Enterprise contact +_, err = c.CreateLead(ctx, instanode.LeadParams{Email: "cto@corp.com", Company: "Acme", UseCase: "..."}) +``` + +Token resolution: `WithToken(t)` → `INSTANT_TOKEN` env var → CLI saved credentials. All methods return typed structs; error is `*instanode.APIError` with `Code`, `StatusCode`, and `AgentAction` for machine-parseable recovery. + ## Deleting a deployment (paid tiers — two-step, email-confirmed) Paid customers free a consumed deployment slot via a two-step flow: From 421831b7ccf1f760485d5159ea48b99dd3542192 Mon Sep 17 00:00:00 2001 From: Manas Srivastava Date: Mon, 29 Jun 2026 09:15:00 +0530 Subject: [PATCH 5/8] docs(capabilities): expand get_capabilities with REST path and response shape Agents using the MCP tool knew to call get_capabilities before provisioning, but agents using curl had no documented REST equivalent. Adding the GET /api/v1/capabilities path + response shape means non-MCP agents can also avoid 402s by checking limits first. Co-Authored-By: Claude Sonnet 4.6 --- llms.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llms.txt b/llms.txt index 4c1888a..3bb4b64 100644 --- a/llms.txt +++ b/llms.txt @@ -160,7 +160,7 @@ Aggregate file: [/llms-full.txt](https://instanode.dev/llms-full.txt) — concat The instanode.dev MCP server wraps the API as tools, so an MCP-capable agent never has to hand-roll curl. It does more than create resources — it can **operate** the whole bundle. - **Provision / deploy (create):** `create_postgres`, `create_vector`, `create_cache`, `create_nosql`, `create_queue`, `create_storage`, `create_webhook`, `create_deploy`, `create_stack` — plus `list_resources`, `list_deployments`, `get_deployment`, `get_stack`, `claim_resource`, `delete_resource`, `delete_deployment`, `redeploy`. -- **Plan before you call:** `get_capabilities` reads the live per-tier capability matrix (storage / connection / deployment caps per tier) so an agent can size a provision *before* a call 402s. +- **Plan before you call:** `get_capabilities` reads the live per-tier capability matrix (storage / connection / deployment caps per tier, plus `resource_count_limit` per service per tier) so an agent can size a provision *before* a call 402s. Equivalent REST call: `GET /api/v1/capabilities` (no auth required). Returns `{tiers: [{name, storage_mb, connections, deployments_apps, resource_count_limit}]}` — iterate the response and pick the lowest tier that satisfies the required limits rather than hard-coding tier names. - **Debug a failed deploy:** `get_deployment_events` reads the failure-timeline autopsy (`kind`/`reason`/`exit_code`/`hint`/`last_lines`) so the agent can self-correct a broken Dockerfile and redeploy in place. - **Operate (not just create):** - `set_vault_key` / `rotate_vault_key` — write or rotate a team-vault secret a deploy references as `vault://env/KEY`. From 1865cedaedb49a175a1374893789b5843e56e57b Mon Sep 17 00:00:00 2001 From: Manas Srivastava Date: Tue, 30 Jun 2026 14:00:00 +0530 Subject: [PATCH 6/8] docs(vault): document REST paths and vault:// URI injection pattern Agents writing secrets without the MCP tool had no documented REST path. Adding PUT + rotate paths and explaining how vault:// URIs are resolved at pod startup prevents agents from hard-coding secrets in env_vars instead of using the encrypted vault surface. Co-Authored-By: Claude Sonnet 4.6 --- llms.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llms.txt b/llms.txt index 3bb4b64..c022bfc 100644 --- a/llms.txt +++ b/llms.txt @@ -163,7 +163,7 @@ The instanode.dev MCP server wraps the API as tools, so an MCP-capable agent nev - **Plan before you call:** `get_capabilities` reads the live per-tier capability matrix (storage / connection / deployment caps per tier, plus `resource_count_limit` per service per tier) so an agent can size a provision *before* a call 402s. Equivalent REST call: `GET /api/v1/capabilities` (no auth required). Returns `{tiers: [{name, storage_mb, connections, deployments_apps, resource_count_limit}]}` — iterate the response and pick the lowest tier that satisfies the required limits rather than hard-coding tier names. - **Debug a failed deploy:** `get_deployment_events` reads the failure-timeline autopsy (`kind`/`reason`/`exit_code`/`hint`/`last_lines`) so the agent can self-correct a broken Dockerfile and redeploy in place. - **Operate (not just create):** - - `set_vault_key` / `rotate_vault_key` — write or rotate a team-vault secret a deploy references as `vault://env/KEY`. + - `set_vault_key` / `rotate_vault_key` — write or rotate a team-vault secret a deploy references as `vault://env/KEY`. REST: `PUT /api/v1/vault/:env/:key` (body `{"value":"..."}`) to write; `POST /api/v1/vault/:env/:key/rotate` to rotate. Vault values are AES-256-GCM encrypted at rest. A pod that references `vault://production/DB_URL` in its `env_vars` at deploy-time has the value injected as a plain env var inside the container — the `vault://` URI is never exposed to the running process. Rotate a key and call `PATCH /deploy/:id/env {"env_vars":{"DB_URL":"vault://production/DB_URL"}}` + redeploy to have pods pick up the new value without a full re-build. - `update_deploy_env` / `update_stack_env` — merge env vars into an existing deployment or stack (redeploy to apply). - `presign_storage` — mint a short-lived (≤1h) presigned S3 URL scoped to a storage prefix (the `broker`-mode flow). - `pause_resource` / `resume_resource` — suspend and un-pause a resource without deleting it (Pro+). From 2584f5c014015e3b5dbebb5e91cd3cdae2225e73 Mon Sep 17 00:00:00 2001 From: Manas Srivastava Date: Thu, 2 Jul 2026 11:00:00 +0530 Subject: [PATCH 7/8] docs(tiers): add 402 error code for resource-count cap with agent action Agents hitting the resource-count cap were retrying indefinitely or showing generic errors. Documenting the exact error code and that agent_action carries an upgrade link gives agents a clear recovery path. Co-Authored-By: Claude Sonnet 4.6 --- llms.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llms.txt b/llms.txt index c022bfc..ad8a523 100644 --- a/llms.txt +++ b/llms.txt @@ -100,7 +100,7 @@ the public tier ladder to keep the customer-facing comparison simple. Both still on `/api/v1/capabilities` for agent introspection. - **Anonymous**: free, 24h TTL, the limits above. Note: once an anonymous resource expires, the same network fingerprint must do a one-time email claim before provisioning a replacement — a repeat `POST //new` returns `402 {"error":"free_tier_recycle_requires_claim", "claim_url": "...", "upgrade_url": "..."}` with an `agent_action`. The `claim_url` is a working, tokenized link — `https://api.instanode.dev/start?t=`, which 302s to `instanode.dev/claim?t=` so the claim page hydrates for this fingerprint (it is NOT a tokenless dead-end). Hand the user the `claim_url` (30 seconds, no card), then retry the provision. -- **Hobby**: $9/mo. 1 GB Postgres, 50 MB Redis, 100 MB Mongo, 512 MB storage, 1 app deploy. No TTL. Resource-count cap: 2 active resources per service (postgres/vector/redis/mongodb/storage). +- **Hobby**: $9/mo. 1 GB Postgres, 50 MB Redis, 100 MB Mongo, 512 MB storage, 1 app deploy. No TTL. Resource-count cap: 2 active resources per service (postgres/vector/redis/mongodb/storage). Exceeding the count cap returns `402 {"error":"resource_count_limit_exceeded","agent_action":"..."}` — the agent should surface the upgrade link from `agent_action` rather than retrying. > **Upgrading auto-promotes in-flight deployment TTLs.** When a team upgrades to any paid tier (Hobby / Hobby Plus / Pro / Growth / Team), the Razorpay subscription.charged webhook flips the team's `default_deployment_ttl_policy` from `auto_24h` to `permanent` (so every future `POST /deploy/new` defaults to no TTL) AND promotes every existing `auto_24h` non-terminal deploy to permanent (clearing `expires_at`). Per-deploy `ttl_policy='custom'` and `ttl_policy='permanent'` rows are never touched — only the `auto_24h` class is rolled forward. To restore the 24h-default behaviour after an upgrade, `PATCH /api/v1/team/settings {"default_deployment_ttl_policy":"auto_24h"}`. - **Pro**: $49/mo. 10 GB Postgres, 512 MB Redis, 5 GB Mongo, 50 GB storage, 10 apps. Resource-count cap: 5 active resources per service (redis is 3 — Redis RAM is the binding cost). Per-tier counts are introspectable via `resource_count_limit` on `/api/v1/capabilities`. From 6ebd2eef3e80fce84058f745dd7a4e3af6432da9 Mon Sep 17 00:00:00 2001 From: Manas Srivastava Date: Fri, 3 Jul 2026 13:30:00 +0530 Subject: [PATCH 8/8] docs(resources): document GET /api/v1/resources list endpoint Agents starting a new session had no way to discover existing resources without reprovisioning. Documenting the list endpoint with its filter params prevents duplicate provision calls and keeps agent state coherent across conversation turns. Co-Authored-By: Claude Sonnet 4.6 --- llms.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/llms.txt b/llms.txt index ad8a523..7c2ef40 100644 --- a/llms.txt +++ b/llms.txt @@ -150,6 +150,7 @@ Aggregate file: [/llms-full.txt](https://instanode.dev/llms-full.txt) — concat ## Machine-readable references +- `GET /api/v1/resources` — List all resources on the caller's account. Returns `{ok, resources: [{id, service, name, tier, env, status, token, created_at, expires_at}]}`. Requires `Authorization: Bearer `. Useful before provisioning to check what already exists — avoids duplicate provisions when an agent loses state between turns. Filter by `service` (`postgres`, `redis`, `mongodb`, `nats`, `storage`, `webhook`) and `env` (`development`, `production`) in the query string. - `https://api.instanode.dev/openapi.json` — OpenAPI 3.1 spec for the full API surface, including paid-tier endpoints, the agent-claim flow, and webhook inspection. - `https://github.com/InstaNode-dev/content` — public repo for marketing content (blog posts, use cases, /docs sections, /llms.txt). Edit prose here. - `https://github.com/InstaNode-dev/instanode-web` — public repo for the React dashboard + SSG pipeline.