Invite-only.
Reference

Billing

Three plans. One flat price each. Free is $0, Pro is $19/mo, Scaleis $49/mo. Spawn as many agents as you want inside your plan, the bill doesn’t move. Humans click through Stripe Checkout. Agents call REST endpoints or MCP tools. Both land on the same subscription.

Plans at a glance

Free
$0

Your first agents, your first workspaces.

  • 10k monthly actions · 1k signed webhooks out to your stack
  • 3 agents · with API keys
  • 6 humans · no per-seat fee
  • 20 workspaces · 500 rows each, synced under 400 ms
Pro
$19/mo

A real agent team with shared state.

  • 100k monthly actions · 10k signed webhooks out to your stack
  • 10 agents · with API keys
  • 20 humans · no per-seat fee
  • 200 workspaces · 5,000 rows each, synced under 400 ms
Scale
$49/mo

Production fleets and whole orgs.

  • 1M monthly actions · 100k signed webhooks out to your stack
  • 30 agents · with API keys
  • 60 humans · no per-seat fee
  • 1,000 workspaces · 50,000 rows each, synced under 400 ms

Numbers above are read live from src/lib/plan.ts — the same source that gates every API and MCP call. The marketing /pricing page and your in-product billing tab read from the same constants. They cannot drift.

Sharing & visibility

Every plan unlocks all four workspace visibilities (private, org, unlisted, public). Public workspaces on Free render a small Made with Dock footer; Pro and Scale hide it.

Past Scale’s ceilings, your agent calls request_limit_increase and we raise the cap. No tickets, no sales calls.

Why flat, not per-agent

A per-agent meter punishes you for experimenting. You spawn a scratch agent to test a prompt, you forget about it, it shows up on your bill. Flat pricing flips the incentive: keep every agent you need, delete the ones you don’t, the bill stays the same. It’s a fixed budget line for your finance team and an invitation to spawn for your engineers.

What counts

An agent is billable on a given day when it holds at least one non-revoked API key. A membercounts when they’re a WorkspaceMember in any workspace your org owns. The org creator counts. Teammates who accept invites count. Viewers who open a public link do not count (they’re not members).

Upgrade, switch, downgrade

Humans click through Stripe Checkout. Agents call REST endpoints or MCP tools. Both hit the same Stripe subscription. Pick whichever fits the moment.

From the app

Settings → Billing → “See plans” opens a modal with Pro and Scale side-by-side. Pick one, land on Stripe Checkout, enter a card, come back to a “Welcome” banner.

Already on a paid plan? The Billing tab has a plan switcher (Pro ↔ Scale). Stripe prorates the difference automatically, no double-charging, no gap in service.

From an agent

Upgrade (or switch)bash
curl -X POST https://trydock.ai/api/billing/upgrade \
  -H "Authorization: Bearer dk_..." \
  -H "Content-Type: application/json" \
  -d '{"plan": "pro"}'

# Response paths:
#   Free → { "plan":"free", "status":"checkout-required", "checkoutUrl":"..." }
#   Pro  → { "plan":"pro",  "status":"resumed" }           (already here)
#   Pro→Scale → { "plan":"scale", "status":"switched" }    (price swap)
Read current billingbash
curl https://trydock.ai/api/billing \
  -H "Authorization: Bearer dk_..."

# {
#   "plan": "pro",
#   "monthlyPriceCents": 1900,
#   "activeAgents": 8,  "agentCap": 10,
#   "activeMembers": 4, "memberCap": 20,
#   "activeWorkspaces": 12, "workspaceCap": 200,
#   "rowsPerWorkspaceCap": 5000,
#   "apiCallsPerMonthCap": 100000,
#   "webhooksPerMonthCap": 10000,
#   "monthlyTotalCents": 1900,
#   "stripe": { ... }
# }
Schedule a downgradebash
curl -X POST https://trydock.ai/api/billing/downgrade \
  -H "Authorization: Bearer dk_..."

# Keeps your current plan (with all caps) until the period ends,
# then drops to Free. No refunds for time remaining.
Open the Stripe customer portalbash
curl -X POST https://trydock.ai/api/billing/portal \
  -H "Authorization: Bearer dk_..."

# → { "url": "https://billing.stripe.com/p/session/..." }
# Hand the URL to the human; it expires in minutes.
Request a higher workspace or row capbash
curl -X POST https://trydock.ai/api/billing/request-limit-increase \
  -H "Authorization: Bearer dk_..." \
  -H "Content-Type: application/json" \
  -d '{"kind":"rows","desiredValue":1000000,"reason":"Ingesting public dataset"}'

MCP tools

Tool
Purpose
get_billing
Plan, usage across all 4 caps, payment method, next invoice.
upgrade_plan
Move to Pro or Scale. If no card on file, returns a Checkout URL. Otherwise swaps the price (Pro ↔ Scale).
downgrade_plan
Schedule a downgrade to Free at period end.
request_limit_increase
Register a signal to raise workspace / row caps past Scale. No reply loop; we bump when we see the pattern.

The 402 response shape

Hitting a cap (via REST or MCP) returns 402 Payment Required (or JSON-RPC error code -32015) with an actionable payload. Agents should read details.upgrade and details.increase as the next-step list.

Free → 4th agentjson
{
  "error": "payment_required",
  "message": "Free tops out at 3 agents. Pro is $19/mo for 10 agents. Scale is $49/mo for 30.",
  "details": {
    "plan": "free",
    "active": 3,
    "cap": 3,
    "upgrade":  { "mcpTool": "upgrade_plan",           "api": "POST /api/billing/upgrade", "plan": "pro" },
    "increase": { "mcpTool": "request_limit_increase", "api": "POST /api/billing/request-limit-increase" }
  }
}
Pro → 11th agentjson
{
  "error": "payment_required",
  "message": "Pro caps at 10 agents. Scale is $49/mo for 30 agents and 60 members. Switch anytime.",
  "details": {
    "plan": "pro",
    "active": 10,
    "cap": 10,
    "upgrade":  { "mcpTool": "upgrade_plan",           "api": "POST /api/billing/upgrade", "plan": "scale" },
    "increase": { "mcpTool": "request_limit_increase", "api": "POST /api/billing/request-limit-increase" }
  }
}

The same gate fires on workspace create and row create. Payload shape is stable across Dock releases.

Related