Configuring Webhooks

Create, change, pause and delete webhook configurations: destination, authorization, triggers, batching, secrets and configuration history.

A webhook configuration names a destination URL, how to authenticate to it, which triggers it reports, and how it batches and retries. Create one or more with POST /webhook/settings. The body is an array, and every element becomes a new configuration:

POST /api/v1/webhook/settings
Content-Type: application/json
[
  {
    "Name": "ERP orders",
    "Active": true,
    "Authorization": {
      "Basic": {
        "Username": "gains-webhooks",
        "Password": "Vq7#pL2m-Xr9"
      }
    },
    "Url": "https://erp.example.com/gains/webhooks",
    "PayloadMaxItems": 100,
    "PayloadInterval": 60,
    "Triggers": {
      "POSubmit": {
        "Enabled": true,
        "Filter": "ReceivingLocation IN ('CHI01', 'DAL02')"
      },
      "TOSubmit": {
        "Enabled": true
      },
      "TaskStatusUpdate": {
        "Enabled": true,
        "Filter": "Status IN ('Completed', 'Failed', 'RejectedFailedProcessing')"
      }
    },
    "RetryHandling": {
      "Attempts": 3,
      "Gap": 10
    },
    "FieldNamingConvention": "PASCAL_CASE"
  }
]

The response returns each new configuration with the Id you use to change it later. Secrets are masked:

{
  "Status": "success",
  "Reason": "New webhook(s) configured. Any updates to a webhook configuration should use the PUT method.",
  "TotalConfigurations": 1,
  "NewConfigurations": [
    {
      "Id": 3,
      "Name": "ERP orders",
      "Active": true,
      "Authorization": {
        "Basic": {
          "Username": "gains-webhooks",
          "Password": "******"
        }
      },
      "Url": "https://erp.example.com/gains/webhooks",
      "PayloadMaxItems": 100,
      "PayloadInterval": 60,
      "Triggers": {
        "POSubmit": {
          "Enabled": true,
          "Filter": "ReceivingLocation IN ('CHI01', 'DAL02')"
        },
        "TOSubmit": {
          "Enabled": true,
          "Filter": null
        },
        "TaskStatusUpdate": {
          "Enabled": true,
          "Filter": "Status IN ('Completed', 'Failed', 'RejectedFailedProcessing')"
        }
      },
      "RetryHandling": {
        "Attempts": 3,
        "Gap": 10
      },
      "ConfigurationMode": "v2",
      "PreferencesUpdated": "2026-10-21 09:42:17",
      "FieldNamingConvention": "PASCAL_CASE"
    }
  ]
}

When a request enables InventoryPolicyUpdate, ForecastWeeklyUpdate or ForecastMonthlyUpdate for the first time, Reason adds that notifications for the trigger may take up to 15 minutes to begin.

Managing configurations

TaskEndpoint
List every configuration (204 when there is none)GET /webhook/settings
Add configurationsPOST /webhook/settings
Replace one configurationPUT /webhook/settings/{ConfigurationId}
Change some settings of one configurationPATCH /webhook/settings/{ConfigurationId}
Delete one configurationDELETE /webhook/settings/{ConfigurationId}
See earlier versions of your configurationsGET /webhook/settings/history

POST always adds configurations; it never changes an existing one.

  • PUT replaces the whole configuration. A setting you leave out takes its default, except FieldNamingConvention, which keeps its current value; Triggers left out means no triggers, and Authorization left out removes authorization. Send every secret again.
  • PATCH changes only what you send. Everything you omit keeps its stored value, secrets included, so you can change a URL or a trigger without resending credentials. Triggers and RetryHandling are replaced as a whole when present, so send every trigger you want to keep.

Settings

SettingWhat it controls
NameYour own label, so you can tell configurations apart.
ActiveWhether payloads are delivered; see Pausing a configuration. An active configuration needs a Url and at least one enabled trigger.
UrlThe destination; see Destination URL.
AuthorizationHow GAINS Connect authenticates to your URL; see Authorization.
PayloadMaxItemsThe most records in one payload.
PayloadIntervalHow long to wait after a successful payload before sending the next.
RetryHandlingHow many times, and how far apart, a failed delivery is tried again; see Retries.
FieldNamingConventionWhether the payloads you receive use PascalCase field names (ItemCode) or camelCase (itemCode); see Webhook Payload Samples.
TriggersWhich events are sent, each with an optional filter; see Webhook Filters.

The API Reference for POST /webhook/settings gives each setting's type, limits and default.

What PayloadMaxItems counts depends on the trigger: orders for the order triggers, SKU-locations for the inventory policy and forecast triggers, and task status changes for TaskStatusUpdate.

Pausing a configuration

Set Active to false with PATCH to stop a configuration delivering:

{
  "Active": false
}
  • Records already queued stay queued and are delivered when you set Active back to true, unless they have waited too long; see Delivery.
  • Events that occur while a configuration is inactive are not delivered to it later.
  • Disabling a trigger stops new records of that trigger being queued for the configuration. Records already queued are still delivered; to discard them, see Discarding queued payloads.

Authorization

Authorization takes exactly one of four schemes, or {} for none.

SchemeWhat GAINS Connect sendsUse it when
HeaderValue as the Authorization header, exactly as givenYour endpoint accepts a fixed API key or a token that does not expire.
BasicHTTP Basic authentication built from Username and PasswordYour endpoint accepts HTTP Basic authentication.
OAuth2ClientCredentialsAn access token it obtains from your identity provider with a client ID and secretYour identity provider issues tokens to clients with a secret.
OAuth2PrivateKeyJwtAn access token it obtains by signing a JWT client assertion with your private keyYour identity provider authenticates clients by certificate instead of a secret.

Header and Basic send the same credential with every delivery, so you rotate it yourself. The OAuth 2.0 schemes send a short-lived token that GAINS Connect renews before it expires; OAuth 2.0 Webhook Destinations explains how tokens are obtained and gives examples for Microsoft Entra ID and Oracle NetSuite. The API Reference for POST /webhook/settings lists the fields of each scheme.

In a PATCH, naming the same scheme changes only the fields you send. Naming a different scheme replaces the old one, so send everything the new scheme needs; {} removes authorization.

Secrets

Secrets (Value, Password, ClientSecret, PrivateKey) are stored encrypted and never returned:

  • A read shows each secret as ******. Sending ****** back is refused, so use PATCH and leave the secret out to keep it.
  • To change a secret, send only the new one with PATCH, under the same scheme.

A secret reads ******(re-enter)

When GET /webhook/settings shows a secret as ******(re-enter) instead of ******, the stored secret can no longer be used. Every delivery for that configuration then fails without reaching your URL, and webhook history records it with status code 502 and this Response:

{
  "error": "credential_must_be_re_entered",
  "errorDescription": "The stored credential for this webhook can no longer be decrypted and must be re-entered."
}

Send the secret again with PATCH /webhook/settings/{ConfigurationId}, naming the same scheme and only the secret:

{
  "Authorization": {
    "Basic": {
      "Password": "Vq7#pL2m-Xr9"
    }
  }
}

A PATCH that leaves Authorization out still works while a secret needs re-entering, so you can change other settings first.

Destination URL

Use an https address that can be reached from the internet, and point Url at the final address: redirects are not followed. Put credentials in Authorization, never in the URL. What your endpoint must do is described in Receiving Webhooks.

Multiple configurations

You can have several configurations, each with its own URL, authorization, triggers, filters and batching. Use them to send the same event to more than one system, or to split one trigger's records between destinations with filters. For example, two configurations that both enable InventoryPolicyUpdate, one with the filter LocationCode IN ('CHI01', 'DAL02') and the other with LocationCode NOT IN ('CHI01', 'DAL02'), divide the policy changes between two systems.

Configurations deliver independently: a destination that is down delays only its own payloads.

Configuration history

GET /webhook/settings/history lists earlier versions of your configurations, as they were before each change or deletion, with CreatedAt and ReplacedAt saying when each version applied. Secrets read as ******. It answers 204 when there is no history.

The history is paged with Cursor and Size: pass Pagination.NextCursor from one page as Cursor to read the next. See Pagination.

Errors

The webhook endpoints (settings, history, test, resend, status and reset) answer these statuses of their own:

StatusWhen
400 Bad RequestA setting or filter is invalid, a test failed, or a resend, status request or reset could not be done. Reason explains which; several validation errors come back together in Reasons.
403 ForbiddenYour credentials do not include webhook access: read access to list configurations, history and queue status, update access to change configurations, test, resend or reset.
404 Not FoundNo configuration, or no webhook, with the Id in the path.

For 401, the other statuses and the error body, see Errors & Retries.

Related


Did this page help you?