GROQ Webhooks: changedAny() syntax and triggering on both create and update
Great questions! You're absolutely right about both issues.
changedAny Syntax with Double Parentheses
The documentation has been updated to reflect this, but you do indeed need double parentheses when using delta::changedAny() with multiple fields:
delta::changedAny((name, phone))The inner parentheses create an array of field names, which is what the function expects.
Triggering on Both Creation and Field Changes
For your second question about firing webhooks on both document creation and updates when specific fields change, the recommended approach is to use a single webhook with a condition that checks for document creation:
_type == "customer" && (delta::changedAny((field1, field2)) || before() == null)The before() == null check returns true when a document is being created (since there's no "before" state). You could also use before()._createdAt == null but before() == null is cleaner and works just as well.
This approach is better than two separate webhooks because:
- It's DRY (Don't Repeat Yourself)
- It reduces redundant HTTP requests and bandwidth usage
- It's easier to maintain
You can also use this pattern in your webhook projection to determine if an event was a creation:
{
"created": before() == null,
// ... other fields
}Note that while webhooks are great for many use cases, consider Sanity Functions for more complex event-driven logic, as they provide serverless compute directly within Sanity with native integration and better security.
Show original thread9 replies
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.