Webhook Rules Documentation
Webhook rules allow you to automatically send HTTP requests to external services when data in your database tables is inserted, updated, or deleted. This enables real-time integration with external systems without the need for polling.
Overview
Webhook rules are triggered automatically when database operations occur on specified tables. Each rule consists of:
- Target Tables: Which database tables to monitor
- Operations: Which CRUD operations trigger the webhook (insert, update, delete, upload)
- Parameters:
- Queries: Fetch additional data using your graphql api prior to sending the webhook.
- Webhook URL & Method: Where to send the HTTP request and how to format it
- Header Template: Tell us how to format your headers with a JMESPath template. more info
- Payload Template: Tell us how to format your params or payload with a JMESPath template. more info
Getting Started - GraphQL API Reference
Query webhook_rule
Retrieve existing webhook rules for your tenant.
Query:
query GetWebhookRules($filter: String, $ordering: String, $limit: Int, $offset: Int) {
webhook_rule(filter: $filter, ordering: $ordering, limit: $limit, offset: $offset) {
ruleid
name
createtime
creatorid
operations
targets
parameters
}
}
Example:
query {
webhook_rule(filter: "name ILIKE '%user%'") {
ruleid
name
operations
targets
parameters
}
}
Mutation create_webhook_rule
Create a new webhook rule.
Mutation:
mutation CreateWebhookRule($input: webhook_ruleInput!) {
create_webhook_rule(input: $input) {
ruleid
name
operations
targets
parameters
}
}
Input Type:
input webhook_ruleInput {
name: String! # Rule name (max 255 characters)
operations: [String!]! # ["insert", "update", "delete", "upload"]
targets: [String!]! # Table names (e.g. ["users", "public.orders"])
parameters: GenericScalar # Configuration object [see Parameters section below](#parameters)
}
Mutation update_webhook_rule
Update an existing webhook rule.
Mutation:
mutation UpdateWebhookRule($ruleid: ID!, $input: webhook_ruleInput!) {
update_webhook_rule(ruleid: $ruleid, input: $input) {
ruleid
name
operations
targets
parameters
}
}
Mutation delete_webhook_rule
Delete a webhook rule.
Mutation:
mutation DeleteWebhookRule($ruleid: ID!) {
delete_webhook_rule(ruleid: $ruleid) {
ruleid
name
}
}
Parameters
The parameters field is a JSON object that configures webhook behavior:
Required Parameters
| Parameter | Type | Description |
|---|---|---|
webhook_url | String | The URL to send the webhook to. Must be a valid HTTP/HTTPS URL with a domain name (no IP addresses). |
http_method | String | HTTP method to use. Valid values: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS. |
Optional Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
payload_template | String | {} | JMESPath template for the request body (see Template System). If http_method is GET this is passed as url params. |
header_template | String | {} | JMESPath template for HTTP headers (see Template System). |
timeout_seconds | Integer | 5 | Request timeout in seconds (1-300). |
queries | Array | [] | Additional queries to run for template data (see Query System). |
query_roleid | Integer | - | Role ID to use when running queries |
Template System
Webhook rules use JMESPath for templating payloads and headers. JMESPath allows you to extract and transform data from the available output values. We have several values exposed based on the operation, you can add to these via the queries parameter. see the complete list we expose
JMESPath Basics
- Simple field access:
tenantid→ Gets the tenant ID - Nested access:
records.new.email→ Gets the email field from new record data - Objects:
{user_id: records.new.id, action: operation}→ Creates a JSON object - Arrays:
[records.new.id, records.new.name]→ Creates an array - Functions:
join(", ", [records.new.first_name, records.new.last_name])→ Calls the JMESPath built in function join.
For more JMESPath syntax and functions, see the official JMESPath documentation.
Template Examples
Basic Payload Template:
{
event_type : 'user_updated',
tenant : tenantid,
table : target,
operation : operation,
data : records.new
}
Header Template with Authorization:
{
Authorization: join(' ', ['Bearer', get_role_token(query_roleid, tenantid, '86400')]),
"Content-Type": 'application/json',
"X-Webhook-Source": 'pxdb'
}
NOTE: You'll need to escape the " in the template when creating the rule like this : "header_template" : "{Authorization: join(' ', ['Bearer', get_role_token(query_roleid, tenantid, '86400')]), \"Content-Type\": 'application/json', \"X-Webhook-Source\": 'devii'}"
Query System
The query system allows you to fetch additional data from your database and make it available in your templates. This is useful when you need related data beyond what's in the triggering record.
Query Structure
Each query in the queries array must be a dictionary with these keys:
| Key | Required | Type | Description |
|---|---|---|---|
query | Yes | String | GraphQL query string with $filter, $ordering, $limit, $offset parameters. Use jinja templating to add variables to your query. |
outvar | Yes | String | Variable name for template access (max 25 chars, must be unique per webhook_rule). This allows you to reference the output in your payload / header templates. |
filter | No | String | Filter expression (see filtering documentation) |
vars | No | Object | Additional query variables (ordering, limit, offset, etc.) |
Query Example
{
"queries": [
{
"query": "query { users(filter: $filter, ordering: $ordering, limit: $limit, offset: $offset) { id name email } }",
"filter": "id = {{ records.new.user_id }}",
"vars": { "limit": 1 },
"outvar": "user_data"
},
{
"query": "query { companies(filter: $filter) { id name } }",
"filter": "id = {{ records.new.company_id }}",
"outvar": "company_info"
}
],
"query_roleid": 123
}
Then in your templates, you can access the query results:
{
user_name: user_data[0].name,
company_name: company_info[0].name
}
Available Output Values
The following values are always available in your templates:
| Variable | Type | Description |
|---|---|---|
tenantid | Integer | Your tenant ID |
target | String | The table name that triggered the webhook |
operation | String | The operation that occurred (insert, update, delete, upload) |
records | Object | The record data (see below) |
get_role_token | Function | Function to generate JWT tokens for API authentication |
Records Structure
The records object contains different data based on the operation:
For INSERT operations:
records.new- The inserted record data
For UPDATE operations:
records.new- The record data after the updaterecords.old- The record data before the update
For DELETE operations:
records.old- The deleted record data
get_role_token Function
The get_role_token function generates JWT tokens for authenticating with APIs:
Syntax: get_role_token(roleid, tenantid, expiration_seconds)
Common usage in header template:
{
Authorization: join(' ', ['Bearer', get_role_token(query_roleid, tenantid, '86400')])
}
Parameters:
roleid: The role ID to generate the token for (query_roleid uses the requester's id)tenantid: Your tenant IDexpiration_seconds: Token expiration time in seconds (default: 86400 = 24 hours)
Examples
Example 1: Simple User Creation Webhook
Scenario: Send a notification when a new user is created.
mutation {
create_webhook_rule(
input: {
name: "User Creation Notification"
operations: ["insert"]
targets: ["users"]
parameters: {
webhook_url: "https://api.example.com/webhooks/user-created"
http_method: "POST"
payload_template: "{event: 'user_created', user_id: records.new.id, user_email: records.new.email}"
header_template: "{\"Content-Type\": \"application/json\", \"X-Source\": \"devii\"}"
}
}
) {
ruleid
name
}
}
Example 2: Complex Order Update with Queries
Scenario: When an order is updated, send webhook with user and product information.
mutation {
create_webhook_rule(
input: {
name: "Order Update with Details"
operations: ["update"]
targets: ["orders"]
parameters: {
webhook_url: "https://api.example.com/webhooks/order-updated"
http_method: "POST"
query_roleid: 123
queries: [
{
query: "query { users(filter: $filter, limit: $limit) { id name email } }"
filter: "id = {{ records.new.user_id }}"
vars: { limit: 1 }
outvar: "customer"
}
{
query: "query { products(filter: $filter) { id name price } }"
filter: "id = {{ records.new.product_id }}"
outvar: "product"
}
]
payload_template: "{order_id: records.new.id, status: records.new.status, customer: customer[0], product: product[?price < `500`], changes: {old_status: records.old.status, new_status: records.new.status}}"
header_template: "{\"Authorization\": join('', ['Bearer ', get_role_token(query_roleid, tenantid, '3600')]), \"Content-Type\": \"application/json\"}"
timeout_seconds: 30
}
}
) {
ruleid
name
}
}
Example 3: GET Request with Query Parameters
Scenario: Trigger a GET request with the record ID as a query parameter.
mutation {
create_webhook_rule(
input: {
name: "User Deletion Cleanup"
operations: ["delete"]
targets: ["users"]
parameters: {
webhook_url: "https://cleanup-service.example.com/user-deleted"
http_method: "GET"
payload_template: "{user_id: records.old.id}"
header_template: "{\"X-API-Key\": \"your-api-key\"}"
}
}
) {
ruleid
name
}
}