Setting your pricing
The marketing.pricing field on your catalog entry — what credits vs free actually changes, and the trap of picking the wrong one.
Your tool has exactly one knob that affects pricing: marketing.pricing on the catalog entry. It's a single string, with two valid values, and it controls whether the deploy wizard asks the tenant to fund their wallet before launching.
That's the whole knob. Read this page once to know which value to pick and what trap to avoid.
The field
marketing is a JSONB column on the apps_catalog table (web/src/lib/db/schema.ts — marketing: jsonb("marketing").notNull().default({})) — the same place your tool's name, category, and marketing copy live. It is not a field on the template manifest — the manifests in runvendo/vendo-templates are JSON files ({slug}/{version}.json) and their schema (cloudflare/deploy-worker/src/schema/manifest.schema.json) has no marketing key. The column is set by a DB seed migration in the Vendo monorepo, typically by a Vendo admin.
Concretely, the seed looks like this (from supabase/migrations/139_hermes_tool.sql):
INSERT INTO tools (slug, name, ..., marketing) VALUES (
'my-tool',
'My Tool',
...,
jsonb_build_object(
'pricing', 'credits',
'replaces', 'HubSpot, Salesforce',
'monthlyCost', '~$15/mo for a typical workload'
)
);The pricing field accepts two values:
| Value | Wizard flow | When to pick it |
|---|---|---|
credits (default) | Account → Configure → Pay → Launch | Any tool that calls the proxy. |
free | Account → Configure → Launch | Tools that never call the proxy. |
If you omit pricing, the catalog defaults to credits. That's the safe default — it just means the wizard runs an extra step.
What credits does
The wizard inserts a "Pay" step between Configure and Launch. The tenant picks an amount, Stripe.js takes their card, and the wallet is funded before POST /api/deploy is called. This keeps the deploy gate from 402'ing them at launch time.
This is what you want for any tool that:
- Calls an LLM (OpenRouter, Anthropic, OpenAI, Gemini through the proxy).
- Calls a TTS or transcription provider (ElevenLabs, AssemblyAI, muapi).
- Sends Telegram messages (
telegram-proxy.vendo.run). - Talks to any
*-proxy.vendo.runhost. - Will be hosted on Vendo's Railway infrastructure (compute billing is metered too, even if your tool calls no third-party APIs).
In other words: almost every tool. If you're in doubt, pick credits.
What free does
The wizard skips the payment step entirely. The tenant goes straight from Configure to Launch without funding their wallet.
This is only safe when your tool genuinely never calls the proxy and never runs on Vendo's compute. In practice that means:
downloadabletools — desktop binaries running on the tenant's hardware, using the tenant's own API keys via BYOK. No proxy, no Vendo compute.npmtools — CLIs the tenant installs locally. Same story.deploymenttools that are pure stateless utilities — vanishingly rare. If your tool needs no third-party APIs and no persistent state, ask whether it should be adownloadableornpmtool instead.
Trap: setting pricing: free on a tool that calls the proxy does not make the calls free. It only hides the wizard's payment step. The tenant lands on a freshly deployed tool with a zero wallet, and the first proxy call returns 402. The tool author looks like the cause.
The flag is a wizard hint, not a billing exemption. There is no "free tier" or "subsidized usage" — every metered call is paid for by someone, and if you didn't set up the tenant to pay, the proxy will refuse it.
How to tell if your tool needs credits
If any of these are true, pick credits:
- Your
vendo.yamllists at least oneintegrations:entry. (Telegram counts. Notion asoauth_app_installdoes not — it has no proxy subdomain.) - Your tool is
tool_type: deployment— your container runs on Vendo's Railway and gets metered for compute, even at idle. - You import the SDK and call any
vendo.proxy.*orvendo.integrations.*method.
If none of the above apply, free is fine. The most common shape for free is a downloadable that uses local resources only — voicebox, openscreen.
How to set it
marketing.pricing is set in a DB seed migration in the Vendo monorepo, alongside the rest of your catalog row. The templates sync action (vendo-templates/.github/workflows/sync.yml) does not touch apps_catalog.marketing — it writes tool_releases.wizard_inputs / wizard_layout. So the workflow is:
- Ship your template manifest JSON to
runvendo/vendo-templates. - Open a PR in the Vendo monorepo with a
supabase/migrations/<n>_<slug>_tool.sqlthat inserts (or updates) theapps_catalogrow with the rightmarketingJSONB, includingpricing. - Vendo admins typically own this step. If you're not a Vendo admin, ask the team to land the seed.
You can flip the value later with a follow-up migration — no new release required. But if your tool's billing surface changes (e.g. you add an integration that calls a proxy provider), update the seed in the same PR.
What you cannot configure
To pre-empt the obvious follow-up questions:
- You cannot set a per-call price. Rates are managed by Vendo, sourced from the upstream provider, and refreshed by a cron. See Per-call costs.
- You cannot set a margin. Margin is a Vendo-side configuration in
margin_rules, resolved per-call. The global default is 20%. You don't see this directly; it's folded into the price a tenant pays. - You cannot set a flat monthly fee. Vendo's model is strictly pay-as-you-go. Tools that want a subscription should run as OSS (BYOK) or as a
downloadablewith their own billing. - You cannot charge a markup of your own. A formal revenue-share or paid-tool program is not yet live — see Revenue share. For now, all tool revenue flows to Vendo (covering the upstream cost plus margin), and tool authors are not paid per-deployment.
The lever you have is which integrations your tool uses and how efficiently it uses them. A tool that batches LLM calls intelligently costs the tenant less and is more likely to keep them around.
Display copy
The marketing JSONB has companion fields the dashboard uses to communicate cost to tenants before they install:
{
"pricing": "credits",
"monthlyCost": "$15-25/mo for typical solo use",
"payAsYouGo": true,
"theyCharge": "free (you pay proxied LLM costs)",
"replaces": "Notion AI, ChatGPT Plus",
"savings": "$20/mo"
}These are display strings — tenants see them on the tool's catalog card and detail page. They don't affect billing. Be honest about cost ranges; over-promising "cheap" and watching tenants get sticker-shock after their first heavy day burns trust faster than anything else.