Articles on: APIs

Webhooks

Webhooks are a powerful tool that enables you to keep track of the subscription events occurring in the Loop system.

This article details the use of Webhooks with Loop and how you can leverage the same for your store.


Contents of the article


How can webhooks help?

Webhooks help stay in sync with the activities that matter most to you and automate actions based on those events. By subscribing to webhooks, you can receive notifications about specific events and use the data payload from the event to trigger custom logic. Overall, webhooks provide a reliable and efficient way to integrate with the Loop system and streamline your workflow.


How to respond to a webhook?

In order to confirm the receipt of data through your webhook, it is important to send a response with a status code in the 200 range, indicating success. If the response falls outside this range, it will signal that the webhook was not received.


Our system has been designed to include a 5-second time-out period for all webhook requests. If a response is not received within this timeframe, the request is considered to have failed.


To ensure that webhook requests are properly processed, our system will automatically retry failed requests over the next 48 hours. However, if a request continues to fail during each retry attempt, our system will take appropriate action and delete the webhook request.


By implementing these measures, we aim to provide a reliable and efficient webhook service that minimizes any potential disruptions to our client's operations.


What are webhook attributes/headers?

Attributes and headers are two important components of a webhook payload. Attributes are key-value pairs that provide additional information about the event that triggered the webhook.


Following are the Webhook attributes for Loop.


Attribute

Description

id

Unique numeric identifier for the webhook.

address

The URI where the webhook should send the POST request when the event occurs.

topic

The event that will trigger the webhook.

version

The version of the API used to populate the body of the webhook.


Headers, on the other hand, are pieces of information sent along with the payload to provide additional context or instructions for how the payload should be processed.


Following are the Webhook headers for Loop.


Header

Description

X-Loop-Webhook-Id

The unique id to identify duplicate entries

X-Loop-Webhook-Api-Version

API version of the payload/webhook

X-Loop-Webhook-Topic

Topic of the webhook e.g., 'subscription/cancelled'

X-Loop-Webhook-Created-At

Date time string when the event was created (remains same in every retry)

X-Loop-Webhook-Delivery-At

Date time string when the webhook is being delivered (also can be referred to as the time when it was retried)

X-Loop-Webhook-Retry-Count

Number of retries/tries done


Supported webhooks


Webhook can be created in Loop for the following topics from object types - "Subscription", "Order", "Customer's Payment Method" and "Flows".


Subscription topics


Topics

Trigger Explanation

Subscription/created

This event will be triggered when a subscription is created.

subscription/paused

This event will be triggered when a subscription is paused.

subscription/updated

This event will be triggered when a subscription is updated.

subscription/cancelled

This event will be triggered when a subscription is cancelled.

subscription/resumed

This event will be triggered when a subscription is resumed.

subscription/reactivated

This event will be triggered when a subscription is reactivated.

subscription/delayed

This event will be triggered when a subscription is delayed.

subscription/rescheduled

This event will be triggered when a subscription is rescheduled.

subscription/expired

This event will be triggered when a subscription is expired.


Example payload:


{
"payload": {
"id": 8888999,
"note": null,
"status": "ACTIVE",
"customer": {
"email": "customer@example.com",
"phone": "+44 7911 123456",
"lastName": "Smith",
"firstName": "John",
"shopifyId": 9876543210123
},
"pausedAt": null,
"createdAt": "2025-02-18T12:00:00.000Z",
"discounts": [],
"hasBundle": false,
"isPrepaid": false,
"lineItems": [
{
"id": 29876543,
"sku": "SHO12345",
"name": "Shoe Cleaner - White / New",
"price": "5.39",
"taxable": true,
"quantity": 1,
"basePrice": "5.99",
"shopifyId": "abc12345-6789-48d5-8e7a-af57a4f46e99",
"attributes": [],
"bundleName": null,
"productTitle": "Shoe Cleaner",
"variantImage": "https://cdn.shopify.com/s/files/example-image-shoe-cleaner.jpg",
"variantTitle": "White / New",
"pricingPolicy": {
"basePrice": {
"amount": "5.99",
"currencyCode": "GBP"
},
"cycleDiscounts": [
{
"afterCycle": 0,
"computedPrice": {
"amount": "5.39",
"currencyCode": "GBP"
},
"adjustmentType": "PERCENTAGE",
"adjustmentValue": {
"percentage": 10
}
}
]
},
"isOneTimeAdded": false,
"discountedPrice": "5.39",
"sellingPlanName": "6 Months",
"isOneTimeRemoved": false,
"productShopifyId": 7654321098765,
"requiresShipping": true,
"variantShopifyId": 9876543211234,
"bundleTransactionId": null,
"discountAllocations": [],
"sellingPlanShopifyId": 123456789
}
],
"shopifyId": 2233445566778,
"cancelledAt": null,
"currencyCode": "GBP",
"billingPolicy": {
"anchors": null,
"interval": "MONTH",
"maxCycles": null,
"minCycles": 6,
"intervalCount": 1
},
"deliveryPrice": 0,
"hasCustomPlan": false,
"nextOrderDate": "2025-04-18T12:00:00.000Z",
"shippingLines": {
"code": "Standard Shipping",
"title": "Standard Shipping (3-5 Business Days)"
},
"deliveryPolicy": {
"interval": "MONTH",
"intervalCount": 1
},
"willAutoResume": false,
"shippingAddress": {
"zip": "EC1A 1BB",
"city": "London",
"company": "John's Supplies",
"address1": "10 Baker Street",
"address2": "Suite 5B",
"lastName": "Smith",
"firstName": "John",
"countryCode": "GB",
"provinceCode": "ENG"
},
"customAttributes": [],
"cancellationReason": null,
"nextOrderDateEpoch": 1745000000,
"totalLineItemPrice": 5.39,
"cancellationComment": null,
"completedOrdersCount": 2,
"originOrderShopifyId": 33445566778899,
"totalLineItemDiscountedPrice": 5.39
},
"metaData": {
"myshopifyDomain": "customshop.myshopify.com"
}
}


Order topics


Topics

Trigger Explanation

order/upcoming

Triggered before processing an order.

order/processed

Triggered when order is processed.

order/partiallyProcessed

Triggered when order is partially processed due to low inventory levels.

order/outOfStock

Triggered when order is out of stock.

order/skipped

Triggered when customer skipped an order.

order/unskipped

Triggered when customer un-skipped an order.

order/paymentFailed

Triggered when customer payment on an order is failed.


Example payload:


{
"payload": {
"id": 9876543,
"note": null,
"status": "FAILED",
"customer": {
"email": "customer@example.com",
"phone": "+44 7890 123456",
"lastName": "Johnson",
"firstName": "Emma",
"shopifyId": 9876543210987
},
"lineItems": [
{
"sku": "MEMB001",
"name": "Exclusive Club Membership",
"price": 15,
"taxable": false,
"quantity": 1,
"shopifyId": null,
"properties": null,
"productTitle": "Exclusive Club Membership",
"variantImage": "https://cdn.shopify.com/s/files/example-membership.png",
"variantTitle": null,
"productShopifyId": 9876543212345,
"requiresShipping": false,
"variantShopifyId": 8765432123456
}
],
"shopifyId": null,
"totalPrice": "15.00",
"totalTaxes": "0.00",
"scheduledAt": "2025-01-10T10:00:00.000Z",
"currencyCode": "GBP",
"subscription": {
"id": 7654321,
"note": null,
"status": "ACTIVE",
"pausedAt": null,
"createdAt": "2024-12-10T10:00:00.000Z",
"discounts": [],
"hasBundle": false,
"isPrepaid": false,
"lineItems": [
{
"id": 54321678,
"sku": "MEMB001",
"name": "Exclusive Club Membership",
"price": "15.00",
"taxable": false,
"quantity": 1,
"basePrice": "15.00",
"shopifyId": "xyz12345-6789-4321-bcde-abcdef123456",
"attributes": [],
"bundleName": null,
"productTitle": "Exclusive Club Membership",
"variantImage": "https://cdn.shopify.com/s/files/example-membership.png",
"variantTitle": null,
"pricingPolicy": {
"basePrice": {
"amount": "15.0",
"currencyCode": "GBP"
},
"cycleDiscounts": [
{
"afterCycle": 0,
"computedPrice": {
"amount": "0.0",
"currencyCode": "GBP"
},
"adjustmentType": "PERCENTAGE",
"adjustmentValue": {
"percentage": 100
}
},
{
"afterCycle": 1,
"computedPrice": {
"amount": "15.0",
"currencyCode": "GBP"
},
"adjustmentType": "PERCENTAGE",
"adjustmentValue": {
"percentage": 0
}
}
]
},
"isOneTimeAdded": false,
"discountedPrice": "15.00",
"sellingPlanName": "£15/Month membership access to exclusive content and discounts.",
"isOneTimeRemoved": false,
"productShopifyId": 9876543211234,
"requiresShipping": false,
"variantShopifyId": 8765432123412,
"bundleTransactionId": null,
"discountAllocations": [],
"sellingPlanShopifyId": 5678901234
}
],
"shopifyId": 5678901234,
"cancelledAt": null,
"currencyCode": "GBP",
"billingPolicy": {
"anchors": null,
"interval": "MONTH",
"maxCycles": null,
"minCycles": 3,
"intervalCount": 1
},
"deliveryPrice": 0,
"hasCustomPlan": false,
"nextOrderDate": "2025-02-10T10:00:00.000Z",
"shippingLines": {
"code": null,
"title": null
},
"deliveryPolicy": {
"interval": "MONTH",
"intervalCount": 1
},
"willAutoResume": false,
"shippingAddress": null,
"customAttributes": [],
"cancellationReason": null,
"nextOrderDateEpoch": 1744500000,
"totalLineItemPrice": 15,
"cancellationComment": null,
"completedOrdersCount": 2,
"originOrderShopifyId": 2345678901234,
"totalLineItemDiscountedPrice": 15
},
"discountCodes": null,
"shippingLines": null,
"subtotalPrice": "15.00",
"paymentAttempt": {
"createdAt": "2025-01-09T09:30:00.000Z",
"errorCode": "insufficient_funds",
"shopifyId": 765432109876,
"updatedAt": "2025-01-09T09:30:00.000Z",
"retryDelay": "2",
"errorMessage": "Insufficient funds in your account.",
"idempotencyKey": "7654321-abc123",
"retryLeftCount": 2,
"retryAttemptCount": 1
},
"shippingAddress": null,
"chargeOffsetDays": null,
"customAttributes": null,
"skippedLineItems": [],
"totalShippingPrice": "0.00",
"totalDiscountAmount": "0.00",
"totalLineItemsPrice": "15.00",
"shippingPriceCurrencyCode": "GBP"
},
"metaData": {
"myshopifyDomain": "membershipstore.myshopify.com"
}
}


Customer's Payment Method


Topics

Trigger Explanation

paymentMethod/updateRequested

Triggered when a customer request's payment method update request from Loop.

paymentMethod/updated

Triggered when customer's payment method is updated.

paymentMethod/expiringSoon

Triggered when customer payment method is about to expire (3 days, 15 days, 30 days before payment method expiring).

Example payload:


{
"payload": {
"id": 4456789,
"name": "John Doe",
"type": "CustomerCreditCard",
"brand": "mastercard",
"customer": {
"email": "customer@example.com",
"phone": "+44 7890 123456",
"lastName": "Doe",
"firstName": "John",
"shopifyId": 1234567890123
},
"riskLevel": "low",
"shopifyId": "a1b2c3d4e5f67890g123h456i789j0kl",
"customerId": 98765432,
"expiryYear": "27",
"lastDigits": "6789",
"expiryMonth": "09",
"customerShopifyId": 987654321098765,
"paypalAccountEmail": null
},
"metaData": {
"myshopifyDomain": "customerstore.myshopify.com"
}
}


Flows


Topics

Trigger Explanation

flow/completed

Triggered when a flow is successfully completed.


List webhook topics


You can list your Webhook topics here


Sample response:


{
"success": true,
"message": "Fetched available topics",
"data": [
"subscription/created",
"subscription/paused",
"subscription/cancelled",
"subscription/resumed",
"subscription/reactivated",
"subscription/expired"
]
}


How to subscribe / unsubscribe Webhook ?


  • How to subscribe to Webhooks?


You can subscribe to a webhook subscription by specifying both an address and a topic.



Sample response of Subscribe Webhook :

{
"success": true,
"message": "Successfully subscribed to the topic",
"data": {
"uuid": "533690245e3d47a683463304bf319136",
"topic": "subscription/cancelled",
"status": "ACTIVE",
"version": "2022-10",
"myshopifyDomain": "aug26-v2release.myshopify.com"
}
}


  • How to unsubscribe from a Webhook?

You can unsubscribe from a webhook subscription using the Loop webhook subscription id.



Sample response of Unsubscribe Webhook :

{
"success": true,
"message": "Successfully unsubscribed from the topic",
"data": {}
}


FAQs


Q: How will I know that incoming webhooks are sent from Loop?


A: Loop webhook headers will always begin with "X-Loop-Webhook-{{variable_name}}".


Q: Can I use regular HTTP for my webhooks connections?


A: No, you must use a secure HTTPS connection in order to connect to our webhooks.


Need help?


There is no need to worry. We are here to assist you. Please contact us at support@loopwork.co or feel free to reach out to us through the chat by clicking on the support beacon located at the bottom right corner.


Regards,


Loop Subscription Team 🙂

Updated on: 18/02/2025

Was this article helpful?

Share your feedback

Cancel

Thank you!