pnpm corsair setup --plugin=kofi api_key=<token>, or the API key field on Hub’s connect page), as the account’s verification_token, or pass it as the key option.
How a delivery arrives:
- Ko-fi POSTs form-encoded, not JSON. The body is
application/x-www-form-urlencodedwith a singledatafield holding the payment as a JSON string.processWebhookrunsJSON.parseon a string body, so neither the raw text norrequest.json()works: the route reads thedatafield and passes the payment object, as below. Use this route for Ko-fi instead of the generic one on the Webhooks page. - Every delivery carries a
verification_token, and the plugin’s handler compares it in constant time before it accepts the payment. With no token configured the delivery is refused rather than accepted: an unverified payment notification would let whoever posted to the URL trigger a sale. The one exception is a delivery Hub forwards withhubVerified: Hub checked the token before forwarding, so the handler skips its own comparison and needs no local token. - Act on a payment in an
afterhook, not abeforehook. Core runswebhookHooks.beforeahead of the handler, so abeforehook also sees deliveries whose token is wrong.afterruns only when the handler accepted the delivery. - A refused delivery answers 401 (missing or wrong token) or 400 (not a Ko-fi payment). Ko-fi retries anything other than a 200, with the same
message_id. - With
multiTenancy, give each tenant its own URL, such ashttps://<your-app>/api/webhook?tenantId=acme, and register it on that tenant’s Ko-fi page. A delivery names no Ko-fi account, so thetenantIdin the URL is what picks the tenant whose token, hooks and data handle it; without it the delivery runs asdefault.
app/api/webhook/route.ts
Donationis a one-off tip.amountis a decimal string such as5.00, not a number, andmessageholds the note left with it.Subscriptionis a membership payment. It fires on every payment, not only the first, so useis_first_subscription_paymentto tell them apart, andtier_namefor the tier.Shop Ordercarriesshop_items, andshippingwhen the goods are physical.Commissionis a paid commission. Ko-fi documents the type but publishes no example payload, so its fields follow the same base shape and may vary.
- There is no API to call.
api.ko-fi.comdoes not resolve, and Ko-fi’s help page says the API is “currently limited to when a payment is made”.webhooks.listEventstherefore returns the documented payment types from Ko-fi’s reference and makes no request. - No payments are stored locally. The plugin declares no entities, and Ko-fi has no API to read payments back from, so keep what you need from each delivery in a
webhookHooksafterhook. When Corsair has a database, each delivery’s event log entry keeps the message ID, amount, currency and whether it was a membership payment. - Ko-fi only tells you about payments. It cannot notify you when a membership ends, so a lapse has to be inferred from the absence of a payment or read from Ko-fi itself.
- A retry keeps its
message_id. Ko-fi retries when the endpoint does not answer 200, with the samemessage_ideach time, so that field is what makes a delivery safe to de-duplicate. - Supporter details are personal data. The plugin logs the amount, currency and message ID, and never the supporter’s name, email, address or message.
- 1 typed API operations
- 4 incoming webhook event types
Setup
1
Install
2
Add the plugin
corsair.ts
multiTenancy: true, scope calls with corsair.withTenant(id). See Quick start for KEK + Hub keys, and Multi-tenancy for account isolation.3
Choose authentication
- API Key (Recommended)
Store the Ko-fi API key before the first call: More: API Key
pnpm corsair setup --plugin=kofi --tenant=acme api_key=<your-key> (leave out --tenant without multiTenancy), or pass it as key in the plugin options. With Hub, each tenant enters their own key on the connect page. See API key auth.4
Connect a tenant
Mint a connect link and send the tenant to it. Hub hosts the page and delivers the result to your app — see Connect / OAuth.
Example API calls
List the payment types Ko-fi can sendWebhooks
This plugin registers 4 webhook event types. Configure the provider to POST to your Corsair HTTP handler, then usewebhookHooks on the plugin factory.
See Webhooks for every event path and payload shape, and Webhooks concept for routing.
What’s next
API reference
Every
kofi.api.* operation with input and output types.Webhooks
Event paths, payloads, and
webhookHooks examples.Connect / OAuth
createLink, Hub delivery, and tenant connect flows.
Use with agents
Expose this plugin’s operations as MCP tools.