Skip to main content

Subscription Webhook Payloads

note

Subscription Webhook Payloads for asynchronous events are available in Saleor 3.2.

Subscription Webhook payloads for synchronous events are available in Saleor 3.6.

Custom Payloads

You can define webhook payloads in Saleor with GraphQL subscriptions. Subscription queries allow you to subscribe to different events and determine what fields should be returned in the payload.

Building Subscription Query

To build a subscription query you can use any GraphQL interface (like GraphQL Playground). Just like with building a GraphQL query, you can use prompts and build the whole subscription from our API. Payload generation will use resolvers/permissions that are normally used in our API. Inside the query, you must define the event type for which the payload will be generated. The event type must be supported by our subscription mechanism (see the list of supported events).

warning

When defining subscription payload for synchronous webhooks some fields are blocked to prevent circular calls.

The example below is a subscription query that would enable listening to the PRODUCT_UPDATED event and requesting the products id and name in the webhook payload:

subscription {
event {
... on ProductUpdated {
product {
id
name
}
}
}
}

Filtering

info

This feature was introduced in Saleor 3.20.

caution

This feature is in the Feature Preview stage, which means that it is available for experimentation and feedback. However, it is still undergoing development and is subject to modifications.

For some webhook events, you can create a filterable subscription. A filterable subscription means the event will be delivered only when the filter input matches the object. This can be useful in below cases:

  • The app is responsible for additional actions for orders that come from a specific channel. For example: US channel requires to receive information that payment was charged, whereas the rest of the channels have auto-capture.
  • Making a separation between different markets. For example: US channel doesn't need to receive order events from UK market.
  • Reducing the traffic between Saleor and apps. Instead of sending each event to each app, the traffic will be reduced as only events for defined channels will be delivered.

All filterable events are available as a top-level subscription field, on the same level as the event field.

Below events can be filtered:

note

Only one top field can be requested as a filterable subscription query. This means that in a single subscription, you cannot define more than one filterable event or mix it with the event field. In that case, a new webhook with a new subscription should be created.

Subscription queries like the below will raise validation error:

subscription {
orderUpdated(channels: ["different-channel"]) {
order {
lines {
id
variant {
id
product {
id
}
}
}
}
}
orderCreated(channels: ["default-channel"]) {
order {
lines {
id
variant {
id
product {
id
}
}
}
}
}
}
Expand ▼
subscription {
event {
... on OrderCreated {
order {
id
}
}
}
orderCreated(channels: ["default-channel"]) {
order {
lines {
id
variant {
id
product {
id
}
}
}
}
}
}
Expand ▼

The example below is a subscription query that triggers a webhook only for orders that belong to given channels: uk, us:

subscription {
orderCreated(channels: ["uk", "us"]) {
order {
id
lines {
id
}
}
}
}
note

The input channels will accept a maximally 500 values. Exceeding this value will cause a validation error.

The above subscription will generate the following webhook payload:

{
"data": {
"orderCreated": {
"order": {
"id": "T3JkZXI6YzhmY2FjMTgtMWQ5Yy00NWRkLTgxMGYtMGIzMTJiYTNjZDYz",
"lines": [
{
"id": "T3JkZXJMaW5lOjkzYTFjZGMxLTQxMzAtNDE4ZC05YTAxLTQyY2I5N2E3ZjIxMw=="
}
]
}
}
}
}

Creating Webhook With Subscription Query

To create a webhook that will have its payload generated using a subscription, you need to use the same mutation as with standard webhooks. The only difference is passing the query field as an input with a subscription query converted to a string. Webhook with the query field defined will be treated as a subscription webhook, and its payload will be generated from the subscription query.

Example asynchronous webhook create mutation for subscription payload:

mutation {
webhookCreate(
input: {
app: "<app_id>"
name: "test_product_updated_subscription"
targetUrl: "<webhook_url>"
asyncEvents: [PRODUCT_UPDATED]
query: "subscription{event{...on ProductUpdated{product{id name}}}}"
}
) {
errors {
field
message
}
webhook {
id
}
}
}
Expand ▼

Example asynchronous webhook payload:

{
"product": {
"id": "UHJvZHVjdDo3Ng==",
"name": "Coconut Juice"
}
}

Example synchronous webhook create mutation for subscription payload:

mutation {
webhookCreate(
input: {
app: "<app_id>"
name: "test_payment_capture_subscription"
targetUrl: "<webhook_url>"
syncEvents: [PAYMENT_CAPTURE]
query: "subscription{event{...on PaymentCaptureEvent{payment{id created}}}}"
}
) {
errors {
field
message
}
webhook {
id
}
}
}
Expand ▼

Example synchronous webhook payload:

{
"payment": {
"id": "UGF5bWVudDoyNDE=",
"created": "2022-08-03T08:52:04.202449+00:00"
}
}

Synchronous Webhooks Payload

Defining synchronous webhook payloads using subscriptions is also supported. Each event subscription type has access to its specific object fields.

caution

Keep in mind that some fields that use the synchronous event to be resolved are not allowed to be called in synchronous webhook payload subscriptions.

Blocked Fields for Subscription Payloads

Synchronous events are not allowed to request fields that are resolved using other synchronous events, which would lead to circular calls of the webhook. Fields that are currently unallowed:

ObjectFields
CheckoutshippingMethods, availableShippingMethods, availablePaymentGateways
OrdershippingMethods, availableShippingMethods

Permissions

Since subscriptions use the Saleor API to define a webhook payload, the App that has the webhook subscribed needs all the permissions that are typically required when querying for specified data. Otherwise, the payload will not be resolved correctly.