Webhooks

Webhooks allow you to subscribe to a number of events in Shopfront that allow you application to act dynamically and avoid having to schedule tasks to query Shopfront (and allows your application to be "live").

Getting Started

To start using Webhooks, you'll first need to register a URL to receive an event.

You can register a webhook by using the register webhook mutation.

We support two different types of webhooks, one which is based off our GraphQL objects and one which is a "thin" layer. If you need most of the details from a GraphQL object then the GraphQL webhooks are the best to use, but if you need only a few pieces of information, it might be better to use the thin webhooks. Some GraphQL webhooks can become quite large (e.g. the deprecated REGISTER_CLOSED_DETAILED can be a couple of megabytes depending upon the number of sales).

An additional benefit of thin register closures are that they process quite quickly on our system, leading to less delay between the event occurring and your application being notified.

GraphQL Webhooks

The GraphQL webhooks return the specified GraphQL object (excluding connections) up to three levels deep. This may change in the future and if it does we will communicate changes directly to you via email. You can check the GraphQL endpoint by using the payload link below for the event you wish to receive.

Event Description Payload
PRODUCT_CREATED A product has been created Product
PRODUCT_UPDATED A product has been updated (not called on inventory changes such as sales) Product
PRODUCT_DELETED A product has been deleted Product
CUSTOMER_CREATED A customer has been created Customer
CUSTOMER_UPDATED A customer has been updated (not called on account balance changes such as sales and payments) Customer
CUSTOMER_DELETED A customer has been deleted Customer
PROMOTION_CREATED A promotion has been created Promotion
PROMOTION_UPDATED A promotion has been updated (not called when a promotion is sold) Promotion
PROMOTION_DELETED A promotion has been deleted Promotion
SALE A sale has been completed (only completed sales are sent through this webhook, not parked sales) Sale
SALE_PARKED A sale has been parked (this could be called multiple times if the sale is parked multiple times) Sale
SALE_MODIFIED A sale has been modified (e.g. date has changed) Sale
SALE_CANCELLED A sale has been cancelled Sale
PAYMENT A customer payment has occurred Customer Payment
ORDER_CREATED An order has been created Order
ORDER_SENT An order has been sent Order
ORDER_RECEIVED An order has been received Order
ORDER_CANCELLED An order has been cancelled Order
REGISTER_CLOSED A register has been closed Register Closure
REGISTER_CLOSED_DETAILED DEPRECATED A register has been closed (this contains every sale that was made during the time the register was open) Register Closure

Thin Webhooks

The payload for thin webhooks returns only the ID of the object that the event occurred on (e.g. if the register was closed, the payload would contain just a single field id that corresponds to the id of the closure).

Event Description
THIN_PRODUCT_CREATED A product has been created
THIN_PRODUCT_UPDATED A product has been updated (not called on inventory changes such as sales)
THIN_PRODUCT_DELETED A product has been deleted
THIN_CUSTOMER_CREATED A customer has been created
THIN_CUSTOMER_UPDATED A customer has been updated (not called on account balance changes such as sales and payments)
THIN_CUSTOMER_DELETED A customer has been deleted
THIN_PROMOTION_CREATED A promotion has been created
THIN_PROMOTION_UPDATED A promotion has been updated (not called when a promotion is sold)
THIN_PROMOTION_DELETED A promotion has been deleted
THIN_SALE A sale has been completed (only completed sales are sent through this webhook, not parked sales)
THIN_SALE_PARKED A sale has been parked (this could be called multiple times if the sale is parked multiple times)
THIN_SALE_UNPARKED A sale has been unparked (removed from the parked sale, this could be called multiple times if the sale is parked multiple times)
THIN_SALE_MODIFIED A sale has been modified (e.g. date has changed)
THIN_SALE_CANCELLED A sale has been cancelled
THIN_CUSTOMER_PAID A customer payment has occurred
THIN_ORDER_CREATED An order has been created
THIN_ORDER_SENT An order has been sent
THIN_ORDER_RECEIVED An order has been received
THIN_ORDER_CANCELLED An order has been cancelled
THIN_REGISTER_CLOSED A register has been closed
THIN_INVENTORY_UPDATED A product's inventory has been changed (e.g. a Sale has been performed or an Invoice has been received)
THIN_TICKET_QUEUED A ticket has been queued for printing
THIN_TICKET_PRINTED A ticket has been printed from the queue
THIN_TICKET_DELETED A ticket has been deleted from the queue

Miscellaneous Webhooks

These are webhooks that don't have a common payload, these are typically related to something that can't be described by the standard webhook system.

Details on the payloads for these can be found on the Custom Webhooks page.

  • INTEGRATION_REVOKED
  • OUTLET_CREATED
  • OUTLET_DELETED
  • REGISTER_CREATED
  • REGISTER_DELETED
  • CUSTOMERS_MERGED
  • INVENTORY_UPDATED
  • BULK_INVENTORY_UPDATED
  • ORDER_ATTACHMENT_UPLOADED
  • ORDER_ATTACHMENT_DELETED

Removing Webhooks

If your webhook is no longer required, you should remove it by using the remove webhook mutation.

Receiving Webhooks

Once your webhook is registered and the event occurs you'll receive a JSON payload that will look similar to:

{
    "id": "12adf-445-a",
    "event": "PRODUCT_CREATED",
    "timestamp": "2019-01-01T10:00:00+00:00",
    "vendor": "example",
    "failedAttempts": 0,
    "webhookId": "11e6...",
    "payload": {},
    "context": null
}

The ID is a unique alphanumeric string for the request, you can use it to ensure that you don't receive the payload multiple times (more about retry rules below).

The event is the corresponding event that you are registered to.

The timestamp is the time the server first attempted to send the message.

The vendor is the subdomain of the vendor that the event belongs to.

The payload varies depending upon the event. See above for the type of payload that will be received corresponding to the event you're registered to.

The context may be present in some webhooks, it contains more information about the event that caused the webhook to fire. If present, its contents will be detailed under the webhook's name in the Custom documentation. If not present, it will be set to null

We also two additional headers X-Shopfront-Signature and X-Shopfront-Signature-Time, these can be used to verify the event came from Shopfront.

Once you've received the webhook you'll need to return a response with a 2xx status (e.g. 200, 204) and with no body. If there is a body or the status is not in the 2xx range, the webhook will be marked as failed.

You'll need to return the response within 30 seconds or the webhook will automatically time out and be marked as failed.

Failing Webhooks

When your webhook fails, it will be put back into the queue to send at a later point in time. After the first failure, it will attempt to send the webhook again in 1 - 5 minutes. If it fails a second or third time, it will attempt to send the webhook again in 5 - 15 minutes (of failure). If it fails a fourth time, the event will be removed from the queue and your webhook will be made inactive which will require you to reactivate it.

If your webhook is failing, but has not yet been made inactive, other events will still fire. This could result in the handling of data out of order. You can use the webhook's timestamp to verify the intended order of each received event.

To reactivate a webhook you'll need to use the activate webhook mutation.

Inactive Webhooks

If your webhook is marked as inactive for at least 6 months, it will be deleted from our system