{
 "slug": "tally",
 "name": "Tally",
 "url": "https://tally.so",
 "domain": "tally.so",
 "category": "forms",
 "category_name": "Forms",
 "tested_at": "2026-10-01",
 "run": "20261001T084910Z",
 "draft": false,
 "reviewed": true,
 "owner_verified": null,
 "origin": "editorial",
 "history": [
  {
   "run": "20261001T084910Z",
   "date": "2026-10-01",
   "level": 4,
   "engine": {
    "runner": "omp",
    "model": null,
    "driver": null,
    "signed": true,
    "inbox": null,
    "robots": "start"
   }
  }
 ],
 "level": 4,
 "level_name": "Runs on its own",
 "level_selfhost": null,
 "entry": "self-start",
 "door": {
  "passed": 1,
  "tries": 1,
  "self_start": true
 },
 "badges": [
  "agent-can-leave"
 ],
 "stages": [
  {
   "key": "in",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: sign-up in a browser"
  },
  {
   "key": "work",
   "label": "Use",
   "state": "yes",
   "text": "Work done: 100% of the core"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "part",
   "text": "Reaches the checkout: stopped at the card form",
   "value": "ready",
   "route": "card_checkout"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: nothing to cancel, deletes its account",
   "left": "deleted"
  }
 ],
 "outcomes": [
  {
   "key": "find",
   "label": "Find",
   "state": "yes",
   "text": "Docs agents can read: llms.txt, an OpenAPI and an MCP server",
   "have": [
    "llms_txt",
    "openapi",
    "mcp"
   ]
  },
  {
   "key": "access",
   "label": "Access",
   "state": "yes",
   "text": "Gets in on its own: sign-up in a browser",
   "stage": "in"
  },
  {
   "key": "use",
   "label": "Use",
   "state": "yes",
   "text": "Work done: 100% of the core",
   "stage": "work"
  },
  {
   "key": "pay",
   "label": "Pay",
   "state": "part",
   "text": "Reaches the checkout: stopped at the card form",
   "value": "ready",
   "route": "card_checkout",
   "stage": "pay"
  },
  {
   "key": "leave",
   "label": "Leave",
   "state": "yes",
   "text": "Leaves on its own: nothing to cancel, deletes its account",
   "left": "deleted",
   "stage": "leave"
  }
 ],
 "access": [
  {
   "key": "browser_signup",
   "label": "Sign-up in a browser",
   "routes": [],
   "minutes": null,
   "core": null
  }
 ],
 "minutes": null,
 "next": {
  "to": 5,
  "text": "Next: pay without a person"
 },
 "stop": null,
 "core": null,
 "scores": {
  "coverage": 64,
  "reliability": null,
  "resilience": null,
  "setup": 90,
  "surface_coverage": null,
  "docs_accuracy": null,
  "docs_completeness": null
 },
 "parts": {
  "holds_up": null,
  "docs_match": null,
  "setup": 90,
  "security": null,
  "standards": []
 },
 "reliability_method": null,
 "resilience": null,
 "stress": [],
 "surface_audit": null,
 "coverage_core": 100,
 "after_wall": null,
 "coverage_source": "reported",
 "driver": null,
 "methodology": 15,
 "rules_date": "2026-10-15",
 "engine": {
  "runner": "omp",
  "model": null,
  "driver": null,
  "signed": true,
  "inbox": null,
  "robots": "start"
 },
 "same_level_drives": 1,
 "drives": 1,
 "works_assisted": null,
 "freshness": "fresh",
 "nothing_to_pay": false,
 "core_gated": false,
 "profiles": {},
 "agent_check": null,
 "agent_pass": null,
 "who_gets_in": {
  "server": {
   "state": "in"
  },
  "signed": {
   "state": "page",
   "kind": "signup",
   "at": "2026-10-12"
  },
  "browser": {
   "state": "in",
   "measured": false
  },
  "our_key": "pending",
  "robots": null,
  "tip": false
 },
 "ladder": {
  "docs": {
   "status": "headless",
   "note": "developers.tally.so/llms.txt, per-page .md, llms-full.txt and openapi.json (25 paths); MCP server documented"
  },
  "signup": {
   "status": "browser",
   "note": "Email + 6-digit code form on tally.so/signup; no documented sign-up API. No visible CAPTCHA (Turnstile token field sent empty)"
  },
  "verify": {
   "status": "browser",
   "note": "Code arrived in ~20 s; read headless from our inbox, entered in the browser; name and password set on /complete-profile"
  },
  "credentials": {
   "status": "browser",
   "note": "API keys only from Settings > API keys in the web app (full access, pinned to version 4 Aug 2026). OAuth with dynamic client registration exists (POST /oauth/register 201) but the authorize step needs a logged-in browser"
  },
  "first_call": {
   "status": "headless",
   "note": "GET /users/me 200 with Bearer key; MCP initialize + tools/list (26 tools) with the same key"
  },
  "first_action": {
   "status": "headless",
   "note": "POST /forms 201 created a published contact form; MCP built a survey with logic and published it"
  },
  "pay": {
   "status": "browser",
   "grade": "P2",
   "rails": [
    "stripe_checkout"
   ],
   "first_party": false,
   "rail_scope": "none",
   "trial_path": "free tier",
   "note": "No 402/x402/MPP/L402/UCP anywhere; not in x402 Bazaar or mpp.dev. Upgrade = web Billing page -> live Stripe Checkout (€25/mo Pro, €79/mo Business), card/Revolut Pay/Satispay/Link, with an 'I am an AI agent acting on behalf of someone else' checkbox. Not completed: no card. No billing API or MCP billing tool"
  },
  "cancel": {
   "status": "n/a",
   "note": "Nothing to cancel: our agent used the free plan.",
   "docs_note": "No plan was started, so nothing to cancel. No billing API; cancellation would be in the web app/Stripe portal [inference, not tested]",
   "docs_grade": "",
   "nothing": "free_plan"
  },
  "delete": {
   "status": "browser",
   "note": "Settings > My account > Delete account (password + acknowledge checkbox) deleted the account at once; API key then returned 401. No API route documented. Forms can be deleted headless (to trash)",
   "left": "deleted",
   "account": true
  }
 },
 "routes": [],
 "checkout": null,
 "docs": null,
 "claims": null,
 "pay_options": {
  "checked": "2026-10-01",
  "source": "drive",
  "options": [
   {
    "id": "stripe-checkout",
    "name": "Stripe Checkout",
    "kind": "checkout",
    "first_party": false,
    "lead": false,
    "networks": [],
    "testnet": false
   }
  ],
  "agentic": [],
  "paid": null,
  "exercised": null,
  "detected_grade": null,
  "trial": {
   "no_card": null,
   "card_required": null,
   "free_plan": true
  },
  "owner_fixes": [
   {
    "title": "Accept x402 or MPP on your API",
    "how": "Answer an unpaid call with 402 and a payment challenge, so an agent pays per call or buys credits without an account or a card."
   },
   {
    "title": "List your plans on Stripe Projects",
    "how": "Agents buy a plan with `stripe projects add`, paid with a token under a spend cap the owner sets (projects.dev)."
   }
  ]
 },
 "surfaces": {
  "api": true,
  "openapi": true,
  "cli": false,
  "sdk": false,
  "mcp": "official",
  "llms_txt": true,
  "webhooks": true,
  "sandbox": false
 },
 "surface_notes": {},
 "can_do": [
  "Create a published form with questions from one API call or a few MCP calls",
  "Add questions, conditional logic and a theme to a form through the official MCP server",
  "Publish a form and get its public link",
  "List, filter, read and delete form submissions",
  "Set up a webhook for new responses, read its delivery log, retry a failed delivery, disable and delete it",
  "Read form metrics, visits over time and visitor breakdowns",
  "Delete forms (they go to trash)"
 ],
 "cannot_do": [
  {
   "what": "Sign up, verify, or create an API key headless",
   "why": "Only the web app does this; no sign-up or key API is documented"
  },
  {
   "what": "Submit a response through a documented API",
   "why": "Only the public form page; the respond endpoint the page uses is undocumented"
  },
  {
   "what": "Create workspaces, folders or invite teammates on the Free plan",
   "why": "Pro features; the API answers 401 'You are not authorized' instead of saying a plan is needed"
  },
  {
   "what": "Get real drop-off analytics on Free",
   "why": "Endpoint returned sample numbers (1000 visitors, 800 starts) with no flag saying it is demo data"
  },
  {
   "what": "Upgrade or cancel a plan headless",
   "why": "Only via web Billing page and Stripe Checkout; no billing API"
  },
  {
   "what": "Delete the account headless",
   "why": "Only in Settings > My account"
  },
  {
   "what": "Connect Notion, Google Sheets, Slack etc.",
   "why": "No API or MCP tool; third-party OAuth in the web app"
  }
 ],
 "blockers": [
  "Account and API key creation need the web app",
  "Team/workspace features are Pro-only"
 ],
 "tips_for_owner": [
  "Let an agent obtain a key without a browser: a documented device-code or headless OAuth flow, or an API to mint keys after email verification",
  "Mark demo data: drop-off analytics on Free returns invented numbers with no isSample flag; return 402/403 with 'requires Pro' or flag it",
  "Return a plan error (402 or 403 with errorType PLAN_REQUIRED) instead of 401 UNAUTHORIZED_ACTION for Pro-gated endpoints like POST /workspaces and invites",
  "Document a submissions-create endpoint (or the public respond endpoint) so agents can test forms end to end",
  "Add an account-delete and billing/portal endpoint to the API",
  "Accept and document the full scope set on dynamic client registration (it silently narrows to 'mcp')"
 ],
 "tips_for_agents": [
  "Use the official MCP server at https://api.tally.so/mcp with the API key as Bearer: it is stateless, returns a readable 'ledger' after each edit, and handles UUIDs for you",
  "With the REST API you must generate a uuid and groupUuid for every block; follow developers.tally.so/documentation/creating-a-contact-form.md",
  "Analytics endpoints need ?period= (e.g. 7d); ignore drop-off numbers on Free plan, they are sample data",
  "invites 'emails' is a comma-separated string, not an array",
  "A 401 UNAUTHORIZED_ACTION from a valid key usually means a Pro feature",
  "Rate limit 100/min, exposed in x-ratelimit-* headers; use webhooks instead of polling"
 ],
 "selfhost": null,
 "summary": "Once a browser sign-up has produced an API key, Tally is very easy for an agent to work with. The REST API, the official MCP server (`https://api.tally.so/mcp`, 26 tools) and the markdown docs let an agent create, edit, publish, read and clean up forms headless, and almost everything worked on the first try. The weak points are at the edges. Sign-up, email verification and API key creation happen only in the web app. Pro-gated endpoints answer `401 You are not authorized` rather than saying a plan is needed. Drop-off analytics on the Free plan returned invented sample numbers. Upgrading and account deletion happen only in the browser.\n\n**Scores:** overall 70 · coverage 64 · access 55 · reliability 78 · docs 86 · core coverage 100%",
 "wall": "API keys only via the website",
 "plan_scope": "",
 "robots_stop": null,
 "robots": null,
 "plain": {
  "summary": "Tally is a form and survey builder. Once an agent gets past a one-time browser sign-up, it can build, publish, fill out, read, and delete forms entirely on its own using Tally's API or its official AI assistant tools. The main thing that stopped it from doing everything by itself was that creating an account and an API key only works through the normal website, not through code.",
  "can_do": [
   "Create a published form with questions using one command or a few AI-assistant steps",
   "Add questions, skip-logic, and styling to a form through the official AI assistant tools",
   "Publish a form and get a shareable link",
   "See, filter, and delete the answers people submit",
   "Set up a notification (webhook) for new answers, check its delivery history, and turn it on or off",
   "See visit and submission stats for a form",
   "Delete forms (they go to a trash folder first)"
  ],
  "cannot_do": [
   {
    "what": "Sign up for an account or create an API key without a browser",
    "why": "Only the website lets you do this; there's no way to do it by code"
   },
   {
    "what": "Use team features like workspaces, folders, or inviting teammates on the free plan",
    "why": "These need a paid plan, and the error message doesn't say so clearly"
   },
   {
    "what": "Get real analytics on drop-off rates on the free plan",
    "why": "It returns made-up sample numbers without labeling them as fake"
   },
   {
    "what": "Upgrade to a paid plan or cancel one without a browser",
    "why": "Payment only happens on the website through Stripe's checkout page"
   },
   {
    "what": "Delete the account without a browser",
    "why": "Only available in the account settings page"
   },
   {
    "what": "Connect other apps like Notion, Google Sheets, or Slack",
    "why": "No automated way to do this; only through the website"
   }
  ]
 },
 "plan_gated": [],
 "reply": null,
 "capabilities": [
  {
   "group": "Forms",
   "capability": "Create a form with questions",
   "weight": "core",
   "source": "https://developers.tally.so/llms.txt (POST /forms), MCP create_new_form"
  },
  {
   "group": "Forms",
   "capability": "Edit form content (questions, blocks, title)",
   "weight": "core",
   "source": "PATCH /forms/{id}, MCP create_blocks/update_text/move_blocks"
  },
  {
   "group": "Forms",
   "capability": "Publish a form and get a share link",
   "weight": "core",
   "source": "status PUBLISHED, MCP publish_form"
  },
  {
   "group": "Responses",
   "capability": "Collect a response from a respondent",
   "weight": "core",
   "source": "tally.so/r/{id} public form (respondent side)"
  },
  {
   "group": "Responses",
   "capability": "Read submissions",
   "weight": "core",
   "source": "GET /forms/{id}/submissions, MCP fetch_submissions"
  },
  {
   "group": "Responses",
   "capability": "Delete a submission",
   "weight": "secondary",
   "source": "DELETE /forms/{id}/submissions/{sid}"
  },
  {
   "group": "Forms",
   "capability": "Delete a form (to trash)",
   "weight": "core",
   "source": "DELETE /forms/{id}"
  },
  {
   "group": "Forms",
   "capability": "List forms and questions",
   "weight": "secondary",
   "source": "GET /forms, GET /forms/{id}/questions"
  },
  {
   "group": "Logic",
   "capability": "Conditional logic / calculations",
   "weight": "secondary",
   "source": "MCP apply_logic, blocks-reference/conditional-logic"
  },
  {
   "group": "Design",
   "capability": "Theme and styling, custom CSS",
   "weight": "secondary",
   "source": "MCP update_styling/update_custom_css"
  },
  {
   "group": "Settings",
   "capability": "Form settings (notifications, redirect, close date, progress bar)",
   "weight": "secondary",
   "source": "PATCH /forms settings, MCP update_settings"
  },
  {
   "group": "Integrations",
   "capability": "Webhooks on new responses",
   "weight": "secondary",
   "source": "/webhooks endpoints"
  },
  {
   "group": "Analytics",
   "capability": "Form analytics (metrics, visits, dimensions, drop-off)",
   "weight": "secondary",
   "source": "/forms/{id}/analytics/*, MCP fetch_insights"
  },
  {
   "group": "Organization",
   "capability": "Create / manage workspaces",
   "weight": "secondary",
   "source": "/workspaces (create requires Pro)"
  },
  {
   "group": "Organization",
   "capability": "Folders",
   "weight": "peripheral",
   "source": "/workspaces/{id}/folders (Pro)"
  },
  {
   "group": "Organization",
   "capability": "Invite teammates / list members",
   "weight": "secondary",
   "source": "/organizations/{id}/invites, /users (Pro for invites)"
  },
  {
   "group": "Integrations",
   "capability": "Native integrations (Notion, Google Sheets, Airtable, Slack, Zapier, Make)",
   "weight": "secondary",
   "source": "tally.so/llms.txt, homepage"
  },
  {
   "group": "Forms",
   "capability": "Collect payments in a form (Stripe)",
   "weight": "peripheral",
   "source": "PAYMENT block; requires Stripe connect in UI"
  },
  {
   "group": "Forms",
   "capability": "File uploads, signatures",
   "weight": "peripheral",
   "source": "blocks reference"
  },
  {
   "group": "Account",
   "capability": "API key management",
   "weight": "peripheral",
   "source": ""
  },
  {
   "group": "Distribution",
   "capability": "Embed / popup widget on own site",
   "weight": "peripheral",
   "source": "developers.tally.so/widgets"
  },
  {
   "group": "Account",
   "capability": "Custom domains, remove branding",
   "weight": "peripheral",
   "source": "pricing (Pro)"
  }
 ],
 "attempts": [
  {
   "capability": "Discover",
   "task": "Find docs, llms.txt, OpenAPI, MCP",
   "route": "none",
   "result": "done",
   "verified": true,
   "evidence": "developers.tally.so/llms.txt 200; openapi.json 25 paths; api.tally.so/mcp documented; /.well-known/oauth-authorization-server JSON with registration_endpoint",
   "notes": "Docs are markdown-per-page, agent friendly"
  },
  {
   "capability": "Account",
   "task": "Sign up with email",
   "route": "none",
   "result": "partial",
   "verified": true,
   "evidence": "Browser: tally.so/signup -> POST api.tally.so/users 200 -> code mail received in ~20s",
   "notes": "No documented signup API; done in browser. Turnstile token sent empty, no visible challenge. First attempt at code entry did not persist the session; second run succeeded"
  },
  {
   "capability": "Account",
   "task": "Verify email + set password",
   "route": "none",
   "result": "partial",
   "verified": true,
   "evidence": "Code 391178 from inbox; browser POST /verify 200, PATCH /users/mZBOez 200 (firstName, lastName, password)",
   "notes": "Browser step"
  },
  {
   "capability": "Account",
   "task": "Create API key",
   "route": "none",
   "result": "partial",
   "verified": true,
   "evidence": "",
   "notes": "Only via web UI; no API/CLI to mint keys"
  },
  {
   "capability": "Account",
   "task": "OAuth dynamic client registration (agent registration)",
   "route": "api",
   "result": "partial",
   "verified": true,
   "evidence": "POST /oauth/register 400 invalid_scope without scope; with scope -> 201 client_id 23d24a63..., scope narrowed to 'mcp'",
   "notes": "Authorize step needs browser login/consent; not completed"
  },
  {
   "capability": "Account",
   "task": "First authenticated call",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "GET /users/me 200; GET /workspaces 200 (empty before first form); GET /forms 200",
   "notes": ""
  },
  {
   "capability": "Create a form with questions",
   "task": "Create published contact form (name, email, message)",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "POST /forms 201 id Eky6ol; GET /forms/Eky6ol returns blocks; GET /questions lists 3 questions",
   "notes": "Client must generate UUIDs for every block and group"
  },
  {
   "capability": "Edit form content (questions, blocks, title)",
   "task": "Rename form via PATCH",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "PATCH /forms/Eky6ol 200 name 'AgentDrive contact form v2'; GET /forms shows new name",
   "notes": ""
  },
  {
   "capability": "Create a form with questions",
   "task": "Build feedback survey with MCP",
   "route": "mcp",
   "result": "done",
   "verified": true,
   "evidence": "MCP create_new_form -> 9qb4AE; create_blocks added 7 blocks (rating, multiple choice, textarea); list_blocks ledger shows them",
   "notes": "MCP works with API key as Bearer; stateless (no session id)"
  },
  {
   "capability": "Conditional logic / calculations",
   "task": "Show 'Why not?' only when answer is No",
   "route": "mcp",
   "result": "done",
   "verified": true,
   "evidence": "apply_logic insert -> CONDITIONAL_LOGIC block 7b087f4b; ledger lists rule; auto-set target hidden",
   "notes": "DSL WHEN..THEN, very clear tool docs"
  },
  {
   "capability": "Theme and styling, custom CSS",
   "task": "Dark theme",
   "route": "mcp",
   "result": "partial",
   "verified": false,
   "evidence": "update_styling -> 'Applied: appearance.theme=DARK'",
   "notes": "Not read back independently"
  },
  {
   "capability": "Form settings (notifications, redirect, close date, progress bar)",
   "task": "Enable progress bar",
   "route": "mcp",
   "result": "failed",
   "verified": false,
   "evidence": "MCP update_settings {settings:{hasProgressBar:true}} -> 'No settings changes were applied'; API PATCH with settings returned 200 but not read back",
   "notes": "Did not look up correct settings key; inconclusive"
  },
  {
   "capability": "Publish a form and get a share link",
   "task": "Publish MCP form",
   "route": "mcp",
   "result": "done",
   "verified": true,
   "evidence": "publish_form -> url https://tally.so/r/9qb4AE status PUBLISHED; list_forms shows PUBLISHED",
   "notes": ""
  },
  {
   "capability": "Webhooks on new responses",
   "task": "Create webhook on contact form",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "POST /webhooks 201 id 3E1X8q; GET /webhooks lists it",
   "notes": "URL https://example.com (no receiver; deliberately fails)"
  },
  {
   "capability": "Collect a response from a respondent",
   "task": "Submit contact form as respondent",
   "route": "none",
   "result": "done",
   "verified": true,
   "evidence": "Browser tally.so/r/Eky6ol -> POST /forms/Eky6ol/respond 200; 'Form submitted'",
   "notes": "Respondent side; no documented submission-create API"
  },
  {
   "capability": "Collect a response from a respondent",
   "task": "Submit survey headless via the respond endpoint",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "MCP fetch_submissions shows it",
   "notes": "Responses empty because I keyed by title uuids"
  },
  {
   "capability": "Read submissions",
   "task": "List submissions + get one",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "GET /forms/Eky6ol/submissions totals all:1; GET /submissions/zEo6KQk 200; filter=completed&limit=1 works",
   "notes": ""
  },
  {
   "capability": "Read submissions",
   "task": "Fetch submissions via MCP",
   "route": "mcp",
   "result": "done",
   "verified": true,
   "evidence": "fetch_submissions 9qb4AE -> 1 submission 4ayb2AA",
   "notes": ""
  },
  {
   "capability": "Webhooks on new responses",
   "task": "Read webhook delivery events, retry, update",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "GET /webhooks/3E1X8q/events -> FAILED 405 (example.com); POST retry 204; PATCH isEnabled=false,url changed 204; GET shows isEnabled:false",
   "notes": ""
  },
  {
   "capability": "Form analytics (metrics, visits, dimensions, drop-off)",
   "task": "Read analytics for contact form",
   "route": "api",
   "result": "partial",
   "verified": true,
   "evidence": "metrics?period=7d visits:1 submissions:1; dimensions country DE city Nürnberg; drop-off returned totalVisitors 1000, formStarts 800 (sample data) with no flag",
   "notes": "period is required though first try omitted it -> clear 400. Drop-off is a Pro feature and on Free returns fabricated sample numbers without saying so"
  },
  {
   "capability": "Form analytics (metrics, visits, dimensions, drop-off)",
   "task": "Insights via MCP",
   "route": "mcp",
   "result": "done",
   "verified": true,
   "evidence": "fetch_insights period 7d -> visits 1, submissions 1",
   "notes": "period required enum; validation error clear"
  },
  {
   "capability": "Create / manage workspaces",
   "task": "Create a second workspace",
   "route": "api",
   "result": "blocked",
   "verified": false,
   "evidence": "POST /workspaces 401 UNAUTHORIZED_ACTION 'You are not authorized to perform this action'",
   "notes": "Pro feature; error says unauthorized, not plan required"
  },
  {
   "capability": "Folders",
   "task": "List folders",
   "route": "api",
   "result": "blocked",
   "verified": false,
   "evidence": "GET /workspaces/wgO27P/folders 401 UNAUTHORIZED_ACTION",
   "notes": "Pro feature"
  },
  {
   "capability": "Invite teammates / list members",
   "task": "List members, invite own second inbox",
   "route": "api",
   "result": "partial",
   "verified": true,
   "evidence": "GET /organizations/mZBayV/users 200 (1 user); POST invites with array -> 400 '\"emails\" must be a string'; with string -> 401 UNAUTHORIZED_ACTION",
   "notes": "Invites likely Pro-gated; invitee was our own inbox an inbox. No mail sent"
  },
  {
   "capability": "Native integrations (Notion, Google Sheets, Airtable, Slack, Zapier, Make)",
   "task": "Connect Notion/Sheets",
   "route": "none",
   "result": "skipped",
   "verified": false,
   "evidence": "No API or MCP tool for integrations",
   "notes": "Needs third-party OAuth in UI; out of scope"
  },
  {
   "capability": "Delete a submission",
   "task": "Delete contact form submission",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "DELETE /submissions/zEo6KQk 204; list totals all:0",
   "notes": ""
  },
  {
   "capability": "Delete a form (to trash)",
   "task": "Delete both forms",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "DELETE /forms/9qb4AE 204, /forms/Eky6ol 204; GET /forms empty; GET /forms/Eky6ol 404 FORM_NOT_FOUND",
   "notes": "Moved to trash; no documented purge"
  },
  {
   "capability": "Webhooks on new responses",
   "task": "Delete webhook",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "DELETE /webhooks/3E1X8q 204; GET /webhooks empty",
   "notes": ""
  },
  {
   "capability": "Pay",
   "task": "Probe agent payment rails",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "No 402 anywhere; x402./mpp./agents. subdomains do not resolve; /.well-known/ucp 404 on tally.so, 401 on api; not in x402 Bazaar or mpp.dev; no payment keywords in llms-full.txt",
   "notes": "None"
  },
  {
   "capability": "Pay",
   "task": "Find the checkout",
   "route": "none",
   "result": "partial",
   "verified": true,
   "evidence": "",
   "notes": "Stopped before any payment field. No trial; free tier is permanent"
  },
  {
   "capability": "Leave",
   "task": "Delete account",
   "route": "none",
   "result": "partial",
   "verified": true,
   "evidence": "Browser Settings > My account > Delete account (password + acknowledge checkbox) -> DELETE /users/mZBOez 204, redirect 'Your account is deleted'; API key afterwards -> 401",
   "notes": "No API route documented"
  },
  {
   "capability": "API hygiene",
   "task": "Rate limit headers",
   "route": "api",
   "result": "done",
   "verified": true,
   "evidence": "x-ratelimit-limit 100, remaining, reset headers present",
   "notes": "Matches docs 100/min"
  },
  {
   "capability": "Collect payments in a form (Stripe)",
   "task": "Add a payment block",
   "route": "none",
   "result": "skipped",
   "verified": false,
   "evidence": "PAYMENT block exists in MCP create_blocks schema; not created",
   "notes": "Needs a Stripe account connected in the web app; we connect no payment accounts"
  },
  {
   "capability": "File uploads, signatures",
   "task": "Add a file upload or signature question",
   "route": "none",
   "result": "skipped",
   "verified": false,
   "evidence": "FILE_UPLOAD and SIGNATURE are listed in the MCP create_blocks schema; not created",
   "notes": "Not tried within the time budget"
  },
  {
   "capability": "Embed / popup widget on own site",
   "task": "Embed a form on a page",
   "route": "none",
   "result": "skipped",
   "verified": false,
   "evidence": "Documented at developers.tally.so/widgets; runs on the client's own site",
   "notes": "No site of ours to embed into"
  },
  {
   "capability": "Custom domains, remove branding",
   "task": "Set a custom domain",
   "route": "none",
   "result": "skipped",
   "verified": false,
   "evidence": "Listed as Pro on the upgrade page (screenshot 019)",
   "notes": "Pro feature; we are on the Free plan"
  },
  {
   "capability": "API key management",
   "task": "List, create or revoke API keys headless",
   "route": "none",
   "result": "skipped",
   "verified": false,
   "evidence": "Docs describe keys only under Settings > API keys; no endpoint in openapi.json",
   "notes": "Key created once in the browser (see Account rows); no API route to manage keys"
  }
 ],
 "stale": false,
 "icon": "/logos/tally.png",
 "monitored": false,
 "verdict": "L4 · Runs on its own: once signed up, Tally gets in on its own and does the work. Sign-up, email verification and the API key page need a browser; there is no documented sign-up API, and our agent found no bot check to pass. From there, the REST API and the official MCP server let it create, edit, publish and clean up forms headless, with no further stop. Paying and account deletion both happen on the web: the upgrade goes through Stripe Checkout, with an option to flag the buyer as an agent, and deleting the account removes it at once.",
 "page": "https://agentdrives.com/tools/tally?via=api"
}