Webhooks

The webhooks field in your app.commerce.config file declares Adobe Commerce webhook subscriptions for your application and configures the subscriptions in the merchant's Admin. Webhooks allow your app to make calls to third-party systems synchronously.

Use Events and webhooks when you need both asynchronous event delivery and synchronous hooks inside Commerce processes.

Responsibilities by role

Webhook configuration spans both the developer who ships the app and the merchant who associates it with Commerce:

Webhook entries

Add a webhooks array at the top level of defineConfig. When present, it must contain at least one entry.

Each entry must use one of these patterns (not both):

Each webhook entry uses the following properties:

Property
Type
Required
Description
label
string
Yes
Display label in App Management.
description
string
Yes
Description shown in App Management.
category
string
No
Used for webhook conflict resolution when multiple apps are using the same webhooks. Possible values are one of validation, append, or modification.
runtimeAction
string
Conditional
Required when not using an explicit url in webhook. Runtime action that resolves the webhook URL.
requireAdobeAuth
boolean
No
When using runtimeAction, indicates whether Adobe authentication is required. Must match the require-adobe-auth setting for that runtime action in app.config.yaml.
webhook
object
Yes
Webhook method, hook identity, HTTP method, and optional fields, rules, headers, timeouts, and either a url or no url (if runtimeAction is set).

Webhook category property

Webhooks are divided into 3 categories (from lower to higher when it comes to possible conflicts with other applications):

data-variant=warning
data-slots=text
If you're not sure which category to choose between append and modification, use modification. Keep in mind that it will not stop the app from install if there are possible conflicts, it only warns the user before install.

Nested webhook object

The webhook object contains the following properties:

Property
Type
Required
Description
webhook_method
string
Yes
Commerce webhook method (for example, observer.catalog_product_save_after).
webhook_type
string
Yes
Typically before or after the original action.
batch_name
string
Yes
Batch identifier. Letters, numbers, and underscores only.
hook_name
string
Yes
Hook identifier within the batch. Same character rules as batch_name.
method
string
Yes
HTTP method for the outbound request (for example, POST).
url
string
Conditional
Absolute HTTPS URL. Required when the entry does not use runtimeAction. Omit when using runtimeAction.
batch_order
number
No
Positive number; order among batches.
priority
number
No
Positive priority hint.
required
boolean
No
Indicates whether the hook is required.
soft_timeout
number
No
Positive soft timeout.
timeout
number
No
Positive timeout.
fallback_error_message
string
No
Message if the webhook fails.
ttl
number
No
Positive TTL for cached responses, when applicable.
fields
array
No
Payload field mapping. Each item: name (required), source (optional).
rules
array
No
Conditional execution. Each item: field, operator, value (all strings).
headers
array
No
Outbound headers. Each item: name, value.

For the full property reference, see Webhooks API.

Example with explicit URL

import { defineConfig } from "@adobe/aio-commerce-lib-app/config"

export default defineConfig({
  metadata: {
    // ...
  },
  webhooks: [
    {
      label: "Product save notification",
      description: "POST to your endpoint after a product is saved",
      category: "append",
      webhook: {
        webhook_method: "observer.catalog_product_save_after",
        webhook_type: "after",
        batch_name: "product_batch",
        hook_name: "notify_external",
        method: "POST",
        url: "https://my-app.example.com/webhooks/product-save",
        headers: [
          { name: "Authorization", value: "Bearer ${token}" },
        ],
        fields: [
          { name: "sku", source: "product.sku" },
        ],
      },
    },
  ],
});

Example with runtime action

Use this pattern so the webhook can execute a runtimeAction in the project.

import { defineConfig } from "@adobe/aio-commerce-lib-app/config"

export default defineConfig({
  metadata: {
    // ...
  },
  webhooks: [
    {
      label: "Cart validation",
      description: "Runtime-resolved endpoint for cart validation",
      category: "validation",
      runtimeAction: "my-package/resolve-webhook-url",
      requireAdobeAuth: true,
      webhook: {
        webhook_method: "observer.checkout_cart_product_add_after",
        webhook_type: "after",
        batch_name: "cart_validation",
        hook_name: "stock_check",
        method: "POST",
        rules: [
          { field: "product.qty", operator: "greaterThan", value: "0" },
        ],
      },
    },
  ],
});

After changing webhooks, rebuild and deploy your app so the pre-app-build hook refreshes generated artifacts. See Build and deploy for more information.

Handler implementation (optional)

When your runtime action handles the HTTP callback from Commerce, you build the response body with Webhook operations (success, exception, add, replace, remove). The @adobe/aio-commerce-lib-webhooks package (responses entry point) provides optional helpers for that workflow. Declaring webhooks in app.commerce.config does not require installing it.