Sell software and digital products through Lemon Squeezy — catalog, customers, orders and refunds, subscriptions, discounts, license keys, checkouts and webhooks.
Lemon Squeezy ships in the w6w first-party pack. It declares 36 actions, 2 health checks, and the host runs its code in a sandbox that never sees the credential.
io.w6w.lemonsqueezyLemon Squeezy is a merchant of record for software and digital products — it sells on your behalf and handles payment collection, sales tax/VAT and invoicing worldwide. This app manages the resulting catalog and customer lifecycle: products, variants and prices; customers; orders, their invoices and refunds; subscriptions, including plan changes, pausing and cancelling; discount codes; license keys generated for licensed products; custom checkout links; and webhook subscriptions for event delivery.
A cancelled subscription keeps running until its ends_at date even though its status flips immediately — a detail this app surfaces explicitly, since a workflow that treats cancellation as instant loss of access would be wrong. Orders cannot be created through this API (they are the result of a checkout being completed by a customer); this app reads and refunds them instead. License key activation/deactivation/validation uses a separate, unauthenticated License API meant for the licensed software itself to call, not the store owner’s API key, and is out of scope here — see the README.
Three routes to the same 36 actions. The Workflow tab is generated from Lemon Squeezy's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.
checkout-create Create a custom checkout URL for a variant, with optional prefill, discount and price overrides.
customer-update Update a customer's details, or archive it. Only filled-in fields are sent.
license-key-list List license keys, optionally filtered by store, order, product or status.
license-key-update Change a license key's activation limit, expiry, or disable it.
order-invoice Generate a downloadable invoice PDF link for an order, addressed to the given billing details.
order-list List orders, newest first, optionally filtered by store, customer email or order number.
order-refund Issue a partial or full refund for an order. Omit the amount for a full refund.
subscription-cancel Cancel an active subscription. The customer keeps access until `ends_at`.
subscription-list List subscriptions, optionally filtered by store, order, product, variant, customer email or status.
subscription-update Change plan, pause/unpause, cancel/resume, or adjust billing timing. Ignored for PayPal-collected subscriptions — see the Customer Portal redirect note.
A workflow step names the app and the action, and the editor fills in the
connection when you pick one. This is the Step shape from the
workflow spec, carrying Lemon Squeezy's real ids.
{
"manifestVersion": "2",
"name": "lemonsqueezy-example",
"steps": [
{
"id": "checkout-create",
"uses": {
"app": "io.w6w.lemonsqueezy",
"action": "checkout-create",
"connection": "conn_YOUR_CONNECTION_ID"
},
"with": {
"storeId": "<storeId>",
"variantId": "<variantId>"
}
}
]
}checkout-create checkout-get checkout-list customer-create customer-get +31 more actions available
Every app-specific value here is a blank you have to fill in. An
app action is reached through the connection that authenticates it, so the
address is a connection id, not the app id — and connections belong to your account,
so a public page cannot know yours. Create one for Lemon Squeezy, then fill in
the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the
parameters that action declares. The call itself is real — the shape is transcribed
from the studio's own snippet builder, which prints the same kind of blanks — but
nothing in it is specific to Lemon Squeezy. The Workflow tab is where this app's
real ids are.
npm install @w6w/sdkyarn add @w6w/sdkpnpm add @w6w/sdkdeno add npm:@w6w/sdkimport { W6wClient, isActionRun } from "@w6w/sdk";
// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();
const envelope = await client.run({
urn: "conn_YOUR_CONNECTION_ID",
action: "checkout-create",
payload: {
storeId: "<value>",
variantId: "<value>",
// customPrice: "<value>",
// redirectUrl: "<value>",
// prefillEmail: "<value>",
// prefillName: "<value>",
// discountCode: "<value>",
// customData: "<value>",
// embed: "<value>",
// locale: "<value>",
// preview: "<value>",
// testMode: "<value>",
// expiresAt: "<value>",
// productOptionsJson: "<value>",
// checkoutOptionsJson: "<value>",
// checkoutDataJson: "<value>",
},
});
if (isActionRun(envelope)) console.log(envelope.value); npm install -g @w6w/cli w6w run conn_YOUR_CONNECTION_ID --action checkout-create --payload '{"storeId":"<value>","variantId":"<value>"}' Give an AI agent Lemon Squeezy — without giving it Lemon Squeezy's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.
One tool call{
"name": "w6w_invoke",
"arguments": {
"ref": "app:io.w6w.lemonsqueezy#checkout-create",
"input": {
"storeId": "<storeId>",
"variantId": "<variantId>"
}
}
}
Every tool names its target with a single ref. The
app: form above doesn't name a connection at all — the
host resolves which of the caller's Lemon Squeezy connections to sign
with, and refuses rather than guesses when the answer is ambiguous.
The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.
Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.
Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.
Lemon Squeezy's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.
The MCP surface is part of the hosted platform. Lemon Squeezy itself is MIT, and the runtime that executes it is source-available (FSL).
Lemon Squeezy declares its own checks, so its health is a property of the app rather than something the host guesses at.
Reads status.lemonsqueezy.com's Oh Dear-powered RSS feed for open incidents. The feed has carried no items since this app was built, so the open/resolved title convention is a best reading rather than a confirmed one — see the module docs.
Reads the documented X-Ratelimit-Limit / X-Ratelimit-Remaining headers off a signed GET /v1/users/me call. 300 calls/minute is the account-wide ceiling.