Skip to main content

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

ParameterTypeDescription
webhook_urlStringThe URL to send the webhook to. Must be a valid HTTP/HTTPS URL with a domain name (no IP addresses).
http_methodStringHTTP method to use. Valid values: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS.

Optional Parameters

ParameterTypeDefaultDescription
payload_templateString{}JMESPath template for the request body (see Template System). If http_method is GET this is passed as url params.
header_templateString{}JMESPath template for HTTP headers (see Template System).
timeout_secondsInteger5Request timeout in seconds (1-300).
queriesArray[]Additional queries to run for template data (see Query System).
query_roleidInteger-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:

KeyRequiredTypeDescription
queryYesStringGraphQL query string with $filter, $ordering, $limit, $offset parameters. Use jinja templating to add variables to your query.
outvarYesStringVariable 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.
filterNoStringFilter expression (see filtering documentation)
varsNoObjectAdditional 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:

VariableTypeDescription
tenantidIntegerYour tenant ID
targetStringThe table name that triggered the webhook
operationStringThe operation that occurred (insert, update, delete, upload)
recordsObjectThe record data (see below)
get_role_tokenFunctionFunction 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 update
  • records.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 ID
  • expiration_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
}
}