project.payment_method.updated
A payment gateway's credentials, link state or on/off switch changes.
When this fires
A payment method on the project changes and at least one of active, linked or a key inside its stored config is different afterwards. The surfaces that raise it:
- Dashboard: the payment method editor on the project's Payment Methods page (credentials and switches), and the on/off toggle on each gateway row.
- Bot: the main bot's payment-method wizard, when a creator walks through connecting a gateway that the project already has in that mode. The wizard re-saves the row through the same path as the dashboard.
- REST:
POST /v1/projects/{project}/payment-methods/{method}/activateand/deactivate. There is noPATCHfor payment methods, so credentials cannot be rotated over REST. - MCP: the
activate_payment_methodanddeactivate_payment_methodtools.
It does not fire when:
- Nothing changed. Activating a gateway that is already on, or re-saving identical credentials, writes nothing and emits nothing.
- A Stripe method is switched on before its Connect account is attached. The call is refused, the row is untouched and there is no event.
- Stripe Connect onboarding completes or is disconnected. Those flows write the row directly and raise no event, even though they change
linkedandactive. - A gateway is first set up. There is no
project.payment_method.createdevent; the first thing you hear about a new gateway is its first update or its deletion. - The gateway is removed. That is
project.payment_method.deleted.
This payload never carries a credential. When gateway keys are rotated,
changes.config.keysnames which keys changed (["clientId"],["secret"]) and nothing else. Neither the old nor the new value is sent, and thepayment_methodsnapshot has noconfigat all.
Caveats
linkedcan appear inchangesbut is not in the snapshot. Read the new value fromchanges.linked.to, or from the payment method endpoint, which does carrylinked.modenever appears inchanges. A row's mode is fixed (live and test are separate rows), so switching a gateway from test to live is a different method with a differentid, not an update to this one.- Every update re-queues a sync of the project's plans to that gateway, so a
plan.sync_completedper active plan usually follows within a minute. Rotated credentials may point at a different gateway account whose catalogue has never seen the plans. config.keysare the gateway's own field names as Subscriby stores them (clientId,secret,publicKey, …), not a normalised list. Stored config is merged on save, so a key is reported when its value changed or was added; keys are never removed through an update.- Switching a gateway off does not affect subscriptions already sold through it; they keep renewing. It only stops new buyers being offered that gateway.
Related events
project.payment_method.deleted: the gateway is removed from the project.plan.sync_completed: the catalogue re-push that follows each update.
Header Parameters
t=<unix seconds>,v1=<hex>: the HMAC-SHA256 of "<t>.<raw body>" under the endpoint's secret. Verify it before acting, and refuse a t more than 300 seconds from now. During a secret rotation a v0= signature under the previous secret may precede v1=.
The event's ULID, bare. The envelope's id is the same ULID prefixed evt_, so strip the prefix before comparing. Deduplicate on it: a retry carries the same id.
The event name, the same as the envelope's type.
Always application/json.
Always Subscriby-Webhooks/1.0.
Request Body
application/json
The signed JSON envelope posted to your endpoint.
TypeScript Definitions
Use the request body type in TypeScript.
The envelope every event is delivered in.
Response Body
Example Requests
/project.payment_method.updatedHow is this guide?