Version
WEBHOOK

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}/activate and /deactivate. There is no PATCH for payment methods, so credentials cannot be rotated over REST.
  • MCP: the activate_payment_method and deactivate_payment_method tools.

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 linked and active.
  • A gateway is first set up. There is no project.payment_method.created event; 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.keys names which keys changed (["clientId"], ["secret"]) and nothing else. Neither the old nor the new value is sent, and the payment_method snapshot has no config at all.

Caveats

  • linked can appear in changes but is not in the snapshot. Read the new value from changes.linked.to, or from the payment method endpoint, which does carry linked.
  • mode never appears in changes. 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 different id, not an update to this one.
  • Every update re-queues a sync of the project's plans to that gateway, so a plan.sync_completed per active plan usually follows within a minute. Rotated credentials may point at a different gateway account whose catalogue has never seen the plans.
  • config.keys are 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.

Ability to subscribe

A token needs this to subscribe an endpoint to the event.

Header Parameters

SB-Signature*string

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=.

SB-Event-Id*string

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.

SB-Event-Name*string

The event name, the same as the envelope's type.

Content-Type*string

Always application/json.

User-Agent*string

Always Subscriby-Webhooks/1.0.

Payload

JSONWhat Subscriby posts to your endpoint

The signed JSON envelope posted to your endpoint.

The envelope every event is delivered in.

Responses

2XXAny success status

Your endpoint acknowledged the delivery. Any 2xx status within 30 seconds marks it delivered; the response body is ignored.

defaultAny other status

Any other status, a connection failure, or no answer within 30 seconds counts as a failed attempt. The delivery is retried 8 times, after 10 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours, 1 day, 3 days; the last failure dead-letters it, and it can be retried from the dashboard or POST /v1/webhook-deliveries/{delivery}/retry. After 20 consecutive failures the endpoint is paused until it is resumed.

How is this guide?

Last updated on