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, andPOST /v1/projects/{project}/resources/{resource}/activate/deactivatefor the switch. - MCP: the
update_resource,activate_resourceanddeactivate_resourcetools.
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
PATCHthat re-sends the stored values, or anactivatecall 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 noupdatedevent precedes it.
There are no
project.resource.activated/deactivatedevents. Switching a resource on or off arrives here, aschanges.active, alongside title and description edits. One save is one event, and it lists only what changed.
Caveats
- The
descriptionis not in theresourcesnapshot, matching every otherproject.resource.*event, but when the description is what changed,changes.description.tocarries 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.activeflip tofalseis "this perk is paused", not "this plan changed". Noplan.updatedfollows. - An
activate/deactivatecall and aPATCHthat setsactiveproduce the same event with the samechanges.activeshape. The payload does not say which route was used. - A swap that also switches an inactive resource back on carries
changes.activebesidechanges.space_id, because the swap reactivates what it repairs. changescontains only the fields that mutated. APATCHcarrying 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.
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.resource.updatedHow is this guide?