Store Hugs Developers

Webhook endpoints

The addresses the shop sends its events to: orders, products, customers, quotations and enquiries.

Reach them through $admin->webhooks. Reading needs the webhooks:read scope, changing them webhooks:write. An endpoint takes only events your key may read: order events need orders:read, product events and catalog.changed products:read, customer events customers:read, and quotation and enquiry events quotations:read. An app sees and manages only the endpoints it made, which are deleted when the merchant disconnects it. Check each delivery with Webhooks::verifySignature.

List webhook endpoints

$admin->webhooks->list(array $query = []): array

One page of the endpoints your key may see, newest first, or oldest change first with updatedSince. Read the next page with meta.nextCursor as cursor. Scope: webhooks:read.

Parameters

Parameter Type
$query array The query fields below, by name.

Query fields

ParameterTypeDescription
limitintegerAt least 1. At most 100. Default 50.
cursorstringmeta.nextCursor (or the cursor in links.next) of the previous page. At most 1000 characters.
updatedSincestring (date-time)Records changed at or after this time (ISO 8601, any offset or Z), oldest change first, for incremental sync.

Returns

An array with data (a list of WebhookEndpoint), links and meta:

FieldTypeDescription
linksobject
links.firstnull
links.lastnull
links.prevstring (uri) or null
links.nextstring (uri) or null
metaobject
meta.pathstring (uri)
meta.perPageinteger
meta.nextCursorstring or null
meta.prevCursorstring or null
dataarray of WebhookEndpoint
data[].idinteger
data[].urlstring (uri)
data[].eventsarray of string
data[].activeboolean
data[].disabledAtstring (date-time) or nullWhen it was turned off after 20 failed deliveries in a row.
data[].createdAtstring (date-time) or null
data[].updatedAtstring (date-time) or null

Errors

StatusWhen
401invalid_api_key: no active Admin key in Authorization: Bearer.
403admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope.
422Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid).
429Rate limited.

Example

$page = $admin->webhooks->list();
$endpoints = $page['data'];

Iterate over every endpoint

$admin->webhooks->all(array $query = []): Generator

Every endpoint matching the query, one at a time, fetching the next page as you read. It takes the same query as list, without cursor. Scope: webhooks:read.

Returns

A generator of WebhookEndpoint arrays, each:

FieldTypeDescription
[].idinteger
[].urlstring (uri)
[].eventsarray of string
[].activeboolean
[].disabledAtstring (date-time) or nullWhen it was turned off after 20 failed deliveries in a row.
[].createdAtstring (date-time) or null
[].updatedAtstring (date-time) or null

Example

foreach ($admin->webhooks->all() as $endpoint) {
    if (! $endpoint['active']) {
        $admin->webhooks->update($endpoint['id'], ['active' => true]);
    }
}

Get a webhook endpoint

$admin->webhooks->get(int $id): array

One endpoint by its id. Scope: webhooks:read.

Parameters

Parameter Type
$id int The endpoint's id.

Returns

A WebhookEndpoint:

FieldTypeDescription
idinteger
urlstring (uri)
eventsarray of string
activeboolean
disabledAtstring (date-time) or nullWhen it was turned off after 20 failed deliveries in a row.
createdAtstring (date-time) or null
updatedAtstring (date-time) or null

Errors

StatusWhen
401invalid_api_key: no active Admin key in Authorization: Bearer.
403admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope.
404not_found: the shop has no such record.
429Rate limited.

Add a webhook endpoint

$admin->webhooks->create(array $input, string|false|null $idempotencyKey = null): array

A new endpoint, which starts on. Its whsec_… signing secret is returned in secret, only this once: keep it to verify deliveries. A shop has at most 10 endpoints (422 limit_reached). Scope: webhooks:write, plus the read scope of each event.

Parameters

Parameter Type
$input array The endpoint's fields, below.
$idempotencyKey string|false|null Your own Idempotency-Key, or false for none. One is made for you when null.

Request fields

FieldTypeDescription
url requiredstring (uri)An https address on the public internet. At most 500 characters.
events requiredarray of string
activebooleanValidated but ignored when creating; a new endpoint is on.

Returns

A CreatedWebhookEndpoint array: the endpoint in data, and its secret:

FieldTypeDescription
dataWebhookEndpoint
data.idinteger
data.urlstring (uri)
data.eventsarray of string
data.activeboolean
data.disabledAtstring (date-time) or nullWhen it was turned off after 20 failed deliveries in a row.
data.createdAtstring (date-time) or null
data.updatedAtstring (date-time) or null
secretstringThe whsec_… signing secret.

Errors

StatusWhen
401invalid_api_key: no active Admin key in Authorization: Bearer.
403admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope.
409idempotency_in_progress: a request with this Idempotency-Key is still running. Retry with the same key after Retry-After seconds; the first answer is then replayed.
422Validation errors, limit_reached, or an idempotency refusal.
429Rate limited.

Example

$created = $admin->webhooks->create([
    'url' => 'https://erp.example.com/storehugs/webhooks',
    'events' => ['order.created', 'order.status_changed', 'product.stock_changed'],
]);
$secret = $created['secret']; // Keep it to verify deliveries.

Update a webhook endpoint

$admin->webhooks->update(
    int $id,
    array $changes,
    DateTimeInterface|string|null $unmodifiedSince = null,
    string|false|null $idempotencyKey = null,
): array

Changes the address, the events or whether the endpoint is on; only what is sent changes. Turning it on resets its failure count. A new address, new events or turning it on needs the read scope of every event it then takes (403 insufficient_scope). Scope: webhooks:write.

Parameters

Parameter Type
$id int The endpoint's id.
$changes array The fields to change, below.
$unmodifiedSince DateTimeInterface|string|null The endpoint's updatedAt as you read it. If it changed since, the change is refused with 409 edit_conflict.
$idempotencyKey string|false|null Your own Idempotency-Key, or false for none.

Request fields

FieldTypeDescription
urlstring (uri)An https address on the public internet. At most 500 characters.
eventsarray of string
activeboolean
updatedAtstring (date-time) or nullThe record's updatedAt as you read it; a newer record gets 409 edit_conflict.

Returns

The changed WebhookEndpoint:

FieldTypeDescription
idinteger
urlstring (uri)
eventsarray of string
activeboolean
disabledAtstring (date-time) or nullWhen it was turned off after 20 failed deliveries in a row.
createdAtstring (date-time) or null
updatedAtstring (date-time) or null

Errors

StatusWhen
401invalid_api_key: no active Admin key in Authorization: Bearer.
403admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope.
404not_found: the shop has no such record.
409edit_conflict (the record changed after If-Unmodified-Since or updatedAt), or idempotency_in_progress.
422Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid).
429Rate limited.

Example

$endpoint = $admin->webhooks->get(2);
$admin->webhooks->update(2, [
    'events' => [...$endpoint['events'], 'order.refunded'],
], unmodifiedSince: $endpoint['updatedAt']);

Delete a webhook endpoint

$admin->webhooks->delete(int $id): void

Deletes an endpoint. Scope: webhooks:write.

Parameters

Parameter Type
$id int The endpoint's id.

Returns

Nothing.

Errors

StatusWhen
401invalid_api_key: no active Admin key in Authorization: Bearer.
403admin_key_in_browser (an Origin header was sent), ip_not_allowed, plan_required(the shop's plan lacks the Integration API, or the feature the endpoint needs), orinsufficient_scope.
404not_found: the shop has no such record.
409idempotency_in_progress: a request with this Idempotency-Key is still running. Retry with the same key after Retry-After seconds; the first answer is then replayed.
422Validation errors ({ message, errors }), or an idempotency refusal(idempotency_key_reused, idempotency_key_invalid).
429Rate limited.