Version
WEBHOOK

project.resource.updated

A resource's title, description or on/off switch changes, or a recovery moves it onto another place.

When this fires

A creator changes one of the three editable fields on a resource (title, description or active) and at least one of them is actually different afterwards. Every surface that can make that change raises it:

  • Dashboard: the resource editor on the project's Resources page, and the on/off switch on each resource row.
  • REST: PATCH /v1/projects/{project}/resources/{resource} for title and description edits, and POST /v1/projects/{project}/resources/{resource}/activate / deactivate for the switch.
  • MCP: the update_resource, activate_resource and deactivate_resource tools.

It also fires when the place behind a resource is swapped: a Disaster Recovery replacement, an automatic failover to a standby, Swap & Grant Resource from the resources list, or the undo of any of those. That event carries changes.space_id with the previous and the new space, changes.kind when the platform upgraded the place in the same move (a group that became a supergroup), and resource.space already reads the new place.

It does not fire when:

  • Nothing changed. A PATCH that re-sends the stored values, or an activate call on a resource that is already active, writes nothing and emits nothing.
  • The place is linked for the first time or removed. That is the connector's link (project.resource.linked) or an unlink (project.resource.unlinked).
  • The resource is deleted. That is project.resource.deleted, and no updated event precedes it.

There are no project.resource.activated / deactivated events. Switching a resource on or off arrives here, as changes.active, alongside title and description edits. One save is one event, and it lists only what changed.

Caveats

  • The description is not in the resource snapshot, matching every other project.resource.* event, but when the description is what changed, changes.description.to carries the new text in full. Read it from there rather than following up with a request to the resource endpoint.
  • Switching a resource off does not touch the plans that sell it. The connector stops granting that one place while the plans keep selling everything else, so a changes.active flip to false is "this perk is paused", not "this plan changed". No plan.updated follows.
  • An activate / deactivate call and a PATCH that sets active produce the same event with the same changes.active shape. The payload does not say which route was used.
  • A swap that also switches an inactive resource back on carries changes.active beside changes.space_id, because the swap reactivates what it repairs.
  • changes contains only the fields that mutated. A PATCH carrying all three fields where only one differs reports one key.

Related events

  • project.resource.created: the manual perk this event later edits.
  • project.resource.linked / project.resource.unlinked: the place bound for the first time or removed, which this event never reports.
  • project.resource.deleted: terminal state for a resource.
  • project.resource.status_changed: the health transition that usually precedes a recovery swap.
  • recovery.resource_replaced / recovery.resource_failed_over: the recovery ledger's own word for the same swap.

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