Agencies, updated
Agency accounts
An agency account manages client accounts from one login. Client accounts are unlimited and free, you can upgrade any client to Pro for $5 a month on your own bill, and you can charge clients a retainer through your own Stripe account. Everything works from the dashboard, the API, the CLI and MCP. It's on the Agency plan, at $39 a month or $390 a year.
Create a client
npx formthunder clients create --name "Harbour Dental" --email owner@example.com --invitecurl -X POST https://formthunder.com/api/v1/clients \
-H "Authorization: Bearer ft_live_..." \
-H "Content-Type: application/json" \
-d '{"name":"Harbour Dental","contact_email":"owner@example.com","invite":true}'Set invite to email the client an invitation. They can then log in to their own dashboard.
Work inside a client account
An agency key acts on a client in three ways. In the CLI, use sets a default.
npx formthunder use CLIENT_ACCOUNT_IDOver the API, send a header.
X-FormThunder-Account: CLIENT_ACCOUNT_IDOver MCP, every tool accepts an account_id. Your AI can list clients, then create forms and set brand kits in the right account.
Create a client account for Harbour Dental, add a contact form to their site and match their brand.Limits
Your agency's own forms have 20,000 submissions a month. A client on the free tier has the Free plan's 250, and an upgraded client has Pro's 10,000. Client accounts don't show the "Powered by" line.
Upgrade a client
An upgrade costs $5 a month and is added to your agency subscription. Downgrading removes the line.
npx formthunder clients upgrade CLIENT_ACCOUNT_ID
npx formthunder clients downgrade CLIENT_ACCOUNT_IDBill a client through your Stripe
Connect your Stripe account from the dashboard, using Stripe Connect. Your clients pay your own Stripe account, and you're the merchant of record.
Agencies can connect from 45 countries, including the US, UK, Canada, Australia, New Zealand, Singapore, Hong Kong, Japan, Malaysia, Thailand, the Philippines, the UAE, Mexico, Brazil and most of Europe. Stripe can't connect agencies in India, Indonesia, Ghana, Kenya, Nigeria or South Africa to FormThunder right now. Agencies there can still use FormThunder and pay for it by card, but can't bill clients through it.
Then set a retainer. It returns a checkout link for you to send to the client, and nothing is charged until they complete it.
curl -X POST https://formthunder.com/api/v1/clients/CLIENT_ACCOUNT_ID/billing \
-H "Authorization: Bearer ft_live_..." \
-H "Content-Type: application/json" \
-d '{"amount_cents":2900,"currency":"usd","interval":"month","description":"Website care plan","auto_upgrade":true}'auto_upgrade defaults to true. It moves the client to Pro once the retainer is active, and back to Free if the retainer is cancelled. Set it to false to manage the client's plan yourself. Retainer status is pending, active, past_due or canceled.
To bill by emailed invoice instead of a card link, add "collection":"invoice". Stripe emails the client an invoice each period, due in 14 days unless you set days_until_due, and the retainer goes active when the first one is paid.
Send a one-off invoice
For something outside the retainer, like a setup fee, send an invoice from your Stripe account. Stripe emails it to the client's contact email straight away and hosts the payment page.
npx formthunder invoices create CLIENT_ACCOUNT_ID --amount 25000 --description "Contact page setup"Or use the API:
curl -X POST https://formthunder.com/api/v1/clients/CLIENT_ACCOUNT_ID/invoices \
-H "Authorization: Bearer ft_live_..." \
-H "Content-Type: application/json" \
-d '{"currency":"usd","days_until_due":14,"items":[{"description":"Contact page setup","amount_cents":25000}]}'GET on the same URL lists them, with status open, paid, void or uncollectible. DELETE .../invoices/INVOICE_ID voids an open one. Refund a paid invoice in your own Stripe dashboard.
Roles
Invite people to a client account with a role of owner, admin, member or viewer.
npx formthunder clients invite CLIENT_ACCOUNT_ID --email owner@example.com --role member