Documentation You are here: start » v » 2.0 » webhooks

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
v:2.0:webhooks [2019/11/06 05:29] – external edit 127.0.0.1v:2.0:webhooks [2023/11/28 17:27] (current) – [Setting up your Webflow collections] marija
Line 3: Line 3:
 ===== Overview ===== ===== Overview =====
  
-Foxy's Webhook functionality allows you to create integrations which subscribe to notifications of new transactions from your Foxy store. When a new transaction is successfully completed, we send a ''HTTP POST'' payload to each of your configured endpoints with information about the completed transaction. Your endpoint can then perform any custom tasks you need, such as updating inventory levels, passing information on to fulfilment services, subscribing customers to mailing lists.+Foxy's Webhook functionality allows you to create integrations which subscribe to notifications of events from your Foxy store, such as new transactions, renewals or changes to subscriptions, or changes to customers. When one of these events occurs, we send a ''HTTP POST'' payload to each of your configured endpoints with information about event's resource. Your endpoint can then perform any custom tasks you need, such as changing access permissions for customers, updating inventory levels, passing information on to fulfilment services, subscribing customers to mailing lists. 
 + 
 +We currently have three different types of Webhook endpoints you can utilise, depending on your needs:
  
-We currently have four different types of Webhook endpoints you can utilise, depending on your needs: 
   * [[#json_webhook|JSON Webhook]]   * [[#json_webhook|JSON Webhook]]
-  * [[#legacy_xml_webhook|Legacy XML Webhook]] 
   * [[#zapier|Zapier]]   * [[#zapier|Zapier]]
   * [[#webflow|Webflow]]   * [[#webflow|Webflow]]
Line 14: Line 14:
 ===== Sending Webhooks & Automatic Retries ===== ===== Sending Webhooks & Automatic Retries =====
  
-When a new transaction is placed and your webhooks are triggered, Foxy will wait for 1 minute for a response from your webhook endpoint. If a webhook fails to respond successfully (that is, if we don't receive a HTTP response code of ''200'', or in the case of the Legacy XML Webhook a response body of just ''foxy'') in that time for any reason, Foxy will automatically reattempt to connect to your endpoint 11 more times within the following hour after it was initially attempted. The retries will get progressively further apart over the hour: ranging from around 1 minute apart up to around 10 minutes apart. If any of the retries are successful, no further attempts will be made.+When webhooks are triggered for one of your subscribed events, Foxy will wait for 1 minute for a response from your webhook endpoint. If a webhook fails to respond successfully (that is, if we don't receive a HTTP response code of ''200'') in that time for any reason, Foxy will automatically reattempt to connect to your endpoint 11 more times within the following hour after it was initially attempted. The retries will get progressively further apart over the hour: ranging from around 1 minute apart up to around 10 minutes apart. If any of the retries are successful, no further attempts will be made
 + 
 +===== Transaction Statuses ===== 
 + 
 +For working with transactions with the webhook, a ''status'' node is included, which identifies what state the transaction is in. This can be important if you are only wanting to perform actions if a transaction has a specific status. Review the table below for details of the different statuses that we currently support: 
 + 
 +^ Status      ^ Description          ^ 
 +| //empty//    | Transaction is complete      | 
 +| ''approved''   | Transaction is complete      | 
 +| ''authorized''   | Transaction is complete, but payment is only authorized      | 
 +| ''capturing''   | //(beta)//. The transaction payment is being captured, check again for final status      | 
 +| ''captured''   | //(beta)//. Transaction is complete, and the payment (that was previously ''authorized'' or ''verified'') has been captured      | 
 +| ''declined''   | The transaction has been declined by the gateway      | 
 +| ''pending''   | The transaction has been completed by the customer, but a final status on the payment has not been received from the gateway. This status will be updated once a final response is received       | 
 +| ''rejected''   | The transaction has been rejected by the gateway      | 
 +| ''voided''   | //(beta)//. The transaction has been voided by the store      | 
 +| ''refunding''   | //(beta)//. The transaction is being refunded, check again for final status      | 
 +| ''refunded''   | //(beta)//. The transaction has been refunded      | 
 +| ''verified''   | The transaction has been completed by the customer, and the payment information has been verified, but no payment has actually been taken      | 
 +| ''problem''   | There was a problem with this transaction, check the transaction report in the administration for details      | 
 + 
 +Those statuses that are marked as "//(beta)//" are part of our beta advanced transaction editing functionality. These statuses are only used if your store is enabled for this functionality.  
 + 
 +The ''verified'' status is only for those gateways that support verifying payment details, if configurable in your payment settings. This could happen if a gateway is set to only verify, or if it was a $0 transaction (like a future subscription) and the payment details were only verified as valid. 
 + 
 +Some gateways will trigger multiple web hooks to be sent for a single transaction, as the status field is changed from pending to a final status - check the next section for details on that.
  
 ===== PayPal, Amazon Pay, and other Hosted Gateways ===== ===== PayPal, Amazon Pay, and other Hosted Gateways =====
Line 22: Line 47:
 </wrap> </wrap>
  
-If you use any of the hosted gateways, note that every transaction may generate more than one notification+If you use any of the hosted gateways (usually where a customer is redirected to a payment page hosted by the gateway itself), note that every transaction may generate more than one notification.
-Every time our IPN (Instant Payment Notification) server gets a notification from the gateway we also send you a notification. Generally, these notifications should arrive to your webhook endpoint in order, but it's possible that these webhooks are sent to your endpoint within a //very// short window (less than 0.5 seconds), and with possible network delays, your endpoint may receive the notifications out of order. Make sure you account for the ''status'' value in your logic. For example, you likely don't want to ship products until the ''status'' has gone from ''pending'' to ''approved''.+
  
-The webhook will include status field which is updated with each notification. Valid status entries include **approved****authorized****declined**, **pending**, and **rejected**. (This node may also be empty if the payment was made by a payment method for which Foxy doesn'currently support statuses.)+Every time our IPN (Instant Payment Notification) server gets a notification from the gateway we also send you a notification. Generallythese notifications should arrive to your webhook endpoint in orderbut it's possible that these webhooks are sent to your endpoint within a //very// short window (less than 0.5 seconds), and with possible network delays, your endpoint may receive the notifications out of order. Make sure you account for the ''status'' value in your logic. For example, you likely don'want to ship products until a transaction ''status'' has gone from ''pending'' to ''approved''.
  
-For instancedepending on your account settings [[/gateways/bitpay|BitPay]] server may send up to 4 notifications for every transactionOther hosted gateways usually send 2 notifications: when the transaction is initiated and when it is complete.+The ''transaction'' webhook will include a status field which is updated with each notificationwhich you can see details on above. (This node may also be empty if the payment was made by a payment method for which Foxy doesn't currently support statuses.
 + 
 +Most hosted gateways usually send 2 notifications: when the transaction is initiated with a ''pending'' status, and when it is complete with it's final status (of either ''approved'', ''declined'' or ''rejected''). There are exceptions to this though, so be sure to test your set up with your chosen gateways and only process transactions that are in your required state.
  
 Here is the current list of hosted gateways which take advantage of the status field: Here is the current list of hosted gateways which take advantage of the status field:
Line 46: Line 72:
   * Mollie   * Mollie
   * Ogone   * Ogone
 +  * PayPal Commerce Platform
   * PayPal Express Checkout   * PayPal Express Checkout
   * PayPal Plus   * PayPal Plus
Line 61: Line 88:
   : The title of the webhook   : The title of the webhook
   ; ''TYPE''   ; ''TYPE''
-  : The type of webhook - ''json'', ''legacy_xml'', ''zapier'', ''webflow''.+  : The type of webhook - ''json'', ''zapier'', ''webflow''.
   ; ''ERROR_MESSAGE''   ; ''ERROR_MESSAGE''
   : The error message received from the endpoint, trimmed to 500 characters. For the JSON Webhook this is the body of the response.   : The error message received from the endpoint, trimmed to 500 characters. For the JSON Webhook this is the body of the response.
Line 69: Line 96:
 Along with the error log, an email will also be sent to the store's configured email address(es) with some general information about the error. Along with the error log, an email will also be sent to the store's configured email address(es) with some general information about the error.
  
-==== Did the transaction complete? ====+==== Did the event complete? ====
  
-The transaction that triggered the webhook still completed successfully, the customer was charged and you'll receive payment for the transaction as your chosen payment gateway processes it.+The event that triggered the webhook still completed successfully. If it was a transaction webhook, the customer was charged and you'll receive payment for the transaction as your chosen payment gateway processes it.
  
 ==== Troubleshooting Webhook Errors ==== ==== Troubleshooting Webhook Errors ====
Line 88: Line 115:
  
 After triggering the transaction to be sent to your webhook again, the system will re-attempt the process again for another hour [[#sending_webhooks_automatic_retries|as detailed above]] - or until it is successful. After triggering the transaction to be sent to your webhook again, the system will re-attempt the process again for another hour [[#sending_webhooks_automatic_retries|as detailed above]] - or until it is successful.
 +
 ====== JSON Webhook ====== ====== JSON Webhook ======
  
 The JSON webhook is, as you may have guessed, a JSON formatted payload sent to your endpoint. The JSON webhook is, as you may have guessed, a JSON formatted payload sent to your endpoint.
 +
 +The below documentation is for our latest version of our webhooks functionality (currently labelled as "Webhooks Next" in the admin). For information related to our previous webhooks version, see the Webhooks Legacy section below.
 +
 +===== Creating a webhook =====
 +
 +JSON webhooks can be created from the "Integrations" section of the FoxyCart administration. Enable the "JSON Webhooks" checkbox within the "webhooks next" section, and you'll be able to specify a new webhook endpoint.
 +
 +Each webhook requires a name, a URL and an encryption key (which will be automatically set with a value). Enter an identifying name and the URL to the endpoint that will be receiving the webhook payload. We'll explain how to create that endpoint in the next section.
 +
 +If you'd like to provide your own encryption key for the webhook, click the "Show secret" button and enter in your own secure key there.
 +
 +==== Subscribed resources ====
 +
 +There are several different resource types that you can subscribe to for the webhooks, one resource per webhook. The following resource types are currently supported:
 +
 +=== Transactions ===
 +
 +Triggered whenever a transaction is completed, it's payment status is updated, or it is captured/refunded/voided (using our beta transaction functionality)
 +
 +Events: ''transaction/created'', ''transaction/captured'', ''transaction/refunded'', ''transaction/voided''
 +
 +=== Subscriptions ===
 +
 +Triggered whenever a subscription resource is created or updated. Subscriptions are created when first purchased as part of a transaction, and an update could include a change to it's next or end date, or the past due amount. Currently not triggered based on creation/update requests from the API (but coming soon).
 +
 +Events: ''subscription/created'', ''subscription/modified''
 +
 +=== Customers ===
 +
 +Triggered whenever a customer resource is created or updated. Currently not triggered based on creation/update requests from the API (but coming soon).
 +
 +Events: ''customer/created'', ''customer/modified''
 +
 +
 +<WRAP center round info 95%>
 +Note: Once you have created a webhook, it's not supported to change the subscribed resource type. If you need to change that for a given resource, you can delete the existing webhook and create another.
 +</WRAP>
 +
 +
 +==== API filter query string ====
 +
 +The JSON webhooks uses our API as the source of data, and by default will just return the base resource as the payload (for example, the transaction webhook will just send the [[https://api.foxycart.com/rels/transaction|transaction]] resource which won't include any details on items or addresses). You can specify a query string value though within the ''API filter query string'' input to adjust what data is sent through, and we provide default query strings for each resource when creating the webhook in the admin.
 +
 +The following are examples of query strings that you might want to use:
 +
 +=== Transactions ===
 +
 +  * Provide all data related to the transaction (default)\\ <code>zoom=applied_taxes,billing_addresses,custom_fields,customer,discounts,items,items:item_category,items:item_options,payments,shipments</code>
 +  * Just send the transaction ID and status\\ <code>fields=id,status</code>
 +
 +=== Subscriptions ===
 +
 +  * Provide all data related to the subscription (default)\\ <code>zoom=customer,customer:default_billing_address,customer:default_shipping_address,transaction_template,transaction_template:discounts,transaction_template:items,transaction_template:items:item_category,transaction_template:items:item_options,transaction_template:applied_coupon_codes,transaction_template:custom_fields</code>
 +
 +=== Customers ===
 +
 +  * Provide all data related to the customer (default)\\ <code>zoom=default_billing_address,default_shipping_address,default_payment_method,customer_addresses</code>
 +
 +==== Saving The Webhook ====
 +
 +To save changes to the webhook, click the "Update Webhooks Next" button below the webhooks.
 +
 +Upon saving, a ''GET'' request is sent to your endpoint to confirm that the URL is valid. You'll need to ensure that your endpoint is able to successfully accept ''GET'' requests for this to complete and allow you to save the webhook.
 +
 +===== Testing Webhooks: Helpful Tips =====
 +
 +It's often helpful to see exactly what the webhook request (sent to your servers) looks like. Though we don't offer this functionality natively, there are a variety of free services that you can use to send and view webhook requests. One we like is [[https://webhook.site/|Webhook.site]]. You can get an endpoint there, configure Foxy to send webhooks to that URI, then review the full request (body and headers). There are others like [[https://hookbin.com/|Hookbin]], or [[https://requestb.in/|Requestb.in]] (which you can set up to self-host if desired, like webhook.site).
 +
 +===== Receiving a webhook =====
 +
 +Once you've configured your webhook - whenever actions happen that relate to the events you're subscribed to, a JSON payload containing information about that event will be sent to your endpoint. If your endpoint is secured with HTTPS, then the data is sent unencrypted ready for you to use. If your endpoint is not secured though, the data will be encrypted using ''AES-256-CBC'' before being sent to your endpoint, meaning you will need to then decrypt it before you can use it.
 +
 +==== Headers ====
 +
 +Any requests made to your webhook's endpoint will also contain several special headers:
 +
 +^ Header ^ Description ^
 +| ''Foxy-Webhook-Event'' | Name of the event that triggered this payload. Review the resources above for the supported events per resource. |
 +| ''Foxy-Webhook-Signature'' | A HMAC SHA256 signature of the payload, using the webhook's encryption key. Used for verifying the contents of the payload. |
 +| ''Foxy-Webhook-Refeed'' | A boolean to signify if this payload has been refed. If ''false'', then this is the first time this specific instance of the event has been triggered. |
 +| ''Foxy-Store-ID'' | The ID of the store that this webhook was triggered for. |
 +| ''Foxy-Store-Domain'' | The current Foxy store domain that this webhook was triggered for. |
 +
 +==== Example Payload ====
 +
 +The JSON payload will follow the same structure as our Hypermedia API. Most of the objects will include the API's ''_links'' array. These contain helpful URI's that could be used to access the specific resources in the API if you're also making use of that. If not, these can be safely ignored.
 +
 +The source of the payload data is our Hypermedia API, so you can use [[https://api.foxycart.com/docs/reference|the documentation]] for the different resources for further information on the data it contains.
 +
 +<WRAP center round info 95%>
 +Webhook payloads will always reflect the most current state of the resource at the time it was sent. If a webhook is resent, it will be the current state of the resource, rather than the state of the resource at the time that it was sent.
 +</WRAP>
 +
 +
 +In the example payloads below - to save space, the ''_links'' arrays have been cleared out. It also assumes the default example API filter query string has been used (as described above).
 +
 +=== Transaction ===
 +
 +<code javascript>{
 +    "_links": { },
 +    "_embedded": {
 +        "fx:customer": {
 +            "_links": { },
 +            "_embedded": {
 +                "fx:attributes": [
 +                    {
 +                        "_links": { },
 +                        "name": "Loyalty Points",
 +                        "value": "100",
 +                        "visibility": "private",
 +                        "date_created": "2020-09-18T08:39:22-0700",
 +                        "date_modified": "2020-09-18T08:39:22-0700"
 +                    },
 +                    {
 +                        "_links": { },
 +                        "name": "Level",
 +                        "value": "Bronze",
 +                        "visibility": "public",
 +                        "date_created": "2020-09-18T08:40:53-0700",
 +                        "date_modified": "2020-09-18T08:40:53-0700"
 +                    },
 +                    {
 +                        "_links": { },
 +                        "name": "Loyalty_Level",
 +                        "value": "Blue",
 +                        "visibility": "public",
 +                        "date_created": "2021-05-17T03:43:36-0700",
 +                        "date_modified": "2021-05-17T03:43:36-0700"
 +                    }
 +                ]
 +            },
 +            "id": 12345678,
 +            "last_login_date": "2022-07-29T04:10:03-0700",
 +            "first_name": "John",
 +            "last_name": "Person",
 +            "email": "john@example.com",
 +            "tax_id": "",
 +            "password_salt": "",
 +            "password_hash": "$P$Bfo4kbFOqal4gqR9RcE/xg2lK75zK1",
 +            "password_hash_type": "phpass",
 +            "password_hash_config": "8",
 +            "forgot_password": "",
 +            "forgot_password_timestamp": null,
 +            "is_anonymous": false,
 +            "date_created": null,
 +            "date_modified": "2022-08-01T08:58:15-0700"
 +        },
 +        "fx:payments": [
 +            {
 +                "_links": { },
 +                "type": "plastic",
 +                "gateway_type": "authorize",
 +                "processor_response": "Authorize.net Transaction ID:123456789",
 +                "processor_response_details": "a:1:{s:20:\"transactionReference\";s:11:\"123456789\";}",
 +                "purchase_order": "",
 +                "cc_number_masked": "xxxxxxxxx4242",
 +                "cc_type": "Visa",
 +                "cc_exp_month": "01",
 +                "cc_exp_year": "2023",
 +                "fraud_protection_score": 0,
 +                "paypal_payer_id": "",
 +                "third_party_id": "",
 +                "amount": 29.99,
 +                "date_created": "2022-08-01T08:58:16-0700",
 +                "date_modified": "2022-08-01T08:58:16-0700"
 +            }
 +        ],
 +        "fx:items": [
 +            {
 +                "_links": { },
 +                "_embedded": {
 +                    "fx:item_options": [
 +                        {
 +                            "_links": { },
 +                            "name": "size",
 +                            "value": "Large",
 +                            "price_mod": 0,
 +                            "weight_mod": 0,
 +                            "date_created": null,
 +                            "date_modified": null
 +                        },
 +                        {
 +                            "_links": { },
 +                            "name": "color",
 +                            "value": "Surprise Me",
 +                            "price_mod": 0,
 +                            "weight_mod": 0,
 +                            "date_created": null,
 +                            "date_modified": null
 +                        }
 +                    ],
 +                    "fx:item_category": {
 +                        "_links": { },
 +                        "admin_email_template_uri": "",
 +                        "customer_email_template_uri": "",
 +                        "gift_recipient_email_template_uri": "https://api.foxycart.com/email_templates/12345",
 +                        "code": "DEFAULT",
 +                        "name": "Default for all products",
 +                        "item_delivery_type": "flat_rate",
 +                        "max_downloads_per_customer": 3,
 +                        "max_downloads_time_period": 24,
 +                        "default_weight": 1,
 +                        "default_weight_unit": "LBS",
 +                        "default_length_unit": "IN",
 +                        "shipping_flat_rate_type": "per_order",
 +                        "shipping_flat_rate": 5,
 +                        "handling_fee_type": "flat_percent_with_minimum",
 +                        "handling_fee": 1,
 +                        "handling_fee_minimum": 0,
 +                        "handling_fee_percentage": 10,
 +                        "customs_value": 0,
 +                        "discount_type": "",
 +                        "discount_name": "Gift Set",
 +                        "discount_details": "single|3-9.98|5-19.96",
 +                        "send_customer_email": false,
 +                        "send_admin_email": false,
 +                        "admin_email": "",
 +                        "date_created": null,
 +                        "date_modified": "2022-07-28T01:44:56-0700"
 +                    }
 +                },
 +                "item_category_uri": "https://api.foxycart.com/item_categories/12345",
 +                "name": "My Subscription",
 +                "price": 24.99,
 +                "quantity": 1,
 +                "quantity_min": 0,
 +                "quantity_max": 0,
 +                "weight": 1,
 +                "code": "mysub",
 +                "parent_code": "",
 +                "discount_name": "",
 +                "discount_type": "",
 +                "discount_details": "",
 +                "subscription_frequency": "1m",
 +                "subscription_start_date": "2022-08-01T00:00:00-0700",
 +                "subscription_next_transaction_date": "2022-09-01T00:00:00-0700",
 +                "subscription_end_date": null,
 +                "is_future_line_item": false,
 +                "shipto": "Me",
 +                "url": "",
 +                "image": "",
 +                "length": 0,
 +                "width": 0,
 +                "height": 0,
 +                "expires": 0,
 +                "date_created": null,
 +                "date_modified": "2022-08-01T08:57:13-0700"
 +            }
 +        ],
 +        "fx:applied_taxes": [
 +            {
 +                "_links": { },
 +                "rate": 0,
 +                "name": "Endpoint",
 +                "amount": 0,
 +                "apply_to_handling": true,
 +                "apply_to_shipping": true,
 +                "is_future_tax": false,
 +                "shipto": "",
 +                "date_created": "2022-08-01T08:58:16-0700",
 +                "date_modified": "2022-08-01T08:58:16-0700"
 +            }
 +        ],
 +        "fx:custom_fields": [
 +            {
 +                "_links": { },
 +                "name": "newsletter_subscribe",
 +                "value": "1",
 +                "is_hidden": false,
 +                "date_created": "2022-08-01T08:58:16-0700",
 +                "date_modified": "2022-08-01T08:58:16-0700"
 +            }
 +        ],
 +        "fx:discounts": [
 +            {
 +                "_links": { },
 +                "code": "mycode",
 +                "amount": -2.5,
 +                "name": "My Coupon",
 +                "display": "-$2.50",
 +                "is_taxable": false,
 +                "is_future_discount": false,
 +                "date_created": "2022-08-01T08:58:16-0700",
 +                "date_modified": "2022-08-01T08:58:16-0700"
 +            }
 +        ],
 +        "fx:shipments": [
 +            {
 +                "_links": { },
 +                "address_name": "Me",
 +                "first_name": "John",
 +                "last_name": "Person",
 +                "company": "",
 +                "address1": "123 Testing Street",
 +                "address2": "",
 +                "city": "LOS ANGELES",
 +                "region": "CA",
 +                "postal_code": "90028",
 +                "country": "US",
 +                "phone": "",
 +                "shipping_service_id": 0,
 +                "shipping_service_description": "Custom Flat Rate Shipping",
 +                "total_item_price": 24.99,
 +                "total_tax": 0,
 +                "total_shipping": 7.5,
 +                "total_price": 29.99,
 +                "date_created": "2022-08-01T08:58:16-0700",
 +                "date_modified": "2022-08-01T08:58:16-0700"
 +            }
 +        ],
 +        "fx:billing_addresses": [
 +            {
 +                "_links": { },
 +                "address_name": "Default Billing Address",
 +                "first_name": "John",
 +                "last_name": "Person",
 +                "company": "",
 +                "address1": "123 Testing Street",
 +                "address2": "",
 +                "city": "LOS ANGELES",
 +                "region": "CA",
 +                "customer_postal_code": "90028",
 +                "customer_country": "US",
 +                "customer_phone": "",
 +                "date_created": null,
 +                "date_modified": "2022-08-01T08:58:16-0700"
 +            }
 +        ]
 +    },
 +    "id": 1976574034,
 +    "display_id": "foo00943",
 +    "is_test": true,
 +    "hide_transaction": false,
 +    "data_is_fed": false,
 +    "type": "transaction",
 +    "source": "cit_ecommerce",
 +    "transaction_date": "2022-08-02T01:28:16+0930",
 +    "locale_code": "en_US",
 +    "customer_first_name": "John",
 +    "customer_last_name": "Person",
 +    "customer_tax_id": "",
 +    "customer_email": "john@example.com",
 +    "customer_ip": "11.22.123.456",
 +    "ip_country": "United States",
 +    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.5 Safari/605.1.15",
 +    "total_item_price": 24.99,
 +    "total_tax": 0,
 +    "total_shipping": 7.5,
 +    "total_future_shipping": 0,
 +    "total_order": 29.99,
 +    "status": "captured",
 +    "date_created": null,
 +    "date_modified": "2022-08-01T08:58:16-0700",
 +    "currency_code": "USD",
 +    "currency_symbol": "$"
 +}</code>
 +
 +Within the payload, the following attributes can be helpful for handling the payload:
 +
 +  ; ''type''
 +  : What type of transaction this was, could be ''transaction'', ''updateinfo'', ''subscription_modification'', ''subscription_renewal'' or ''subscription_cancellation''
 +
 +=== Subscription ===
 +
 +<code javascript>{
 +    "_links": {
 +        // Note: These two links are included in order to illustrate where you can obtain subscription-related URLs. There are many other links included in the webhook, and you can explore them in our API documentation at https://api.foxycart.com.
 +        "fx:sub_token_url": {
 +            "href": "https://your-store.foxycart.com/cart?sub_token=3599338e72595b521d62b3ca7e286c212346ec3fc6f859ef139e5d9796900fad",
 +            "title": "This Sub Token",
 +            "type": "text/html"
 +        },
 +        "fx:sub_modification_url": {
 +            "href": "https://your-store.foxycart.com/cart?sub_token=3599338e72595b521d62b3ca7e286c212346ec3fc6f859ef139e5d9796900fad&redirect=https://your-store.com",
 +            "title": "URL to modify this subscription",
 +            "type": "text/html"
 +        }
 +     },
 +    "_embedded": {
 +        "fx:customer": {
 +            "_links": { },
 +            "_embedded": {
 +                "fx:attributes": [
 +                    {
 +                        "_links": { },
 +                        "name": "Loyalty Points",
 +                        "value": "100",
 +                        "visibility": "private",
 +                        "date_created": "2020-09-18T08:39:22-0700",
 +                        "date_modified": "2020-09-18T08:39:22-0700"
 +                    },
 +                    {
 +                        "_links": { },
 +                        "name": "Level",
 +                        "value": "Bronze",
 +                        "visibility": "public",
 +                        "date_created": "2020-09-18T08:40:53-0700",
 +                        "date_modified": "2020-09-18T08:40:53-0700"
 +                    },
 +                    {
 +                        "_links": { },
 +                        "name": "Loyalty_Level",
 +                        "value": "Blue",
 +                        "visibility": "public",
 +                        "date_created": "2021-05-17T03:43:36-0700",
 +                        "date_modified": "2021-05-17T03:43:36-0700"
 +                    }
 +                ],
 +                "fx:default_billing_address": {
 +                    "_links": { },
 +                    "address_name": "Default Billing Address",
 +                    "first_name": "John",
 +                    "last_name": "Person",
 +                    "company": "",
 +                    "address1": "123 Testing Street",
 +                    "address2": "",
 +                    "city": "LOS ANGELES",
 +                    "region": "CA",
 +                    "postal_code": "90028",
 +                    "country": "US",
 +                    "phone": "",
 +                    "is_default_billing": true,
 +                    "is_default_shipping": false,
 +                    "date_created": null,
 +                    "date_modified": "2022-08-01T08:58:15-0700"
 +                },
 +                "fx:default_shipping_address": {
 +                    "_links": { },
 +                    "address_name": "Me",
 +                    "first_name": "John",
 +                    "last_name": "Person",
 +                    "company": "",
 +                    "address1": "123 Testing Street",
 +                    "address2": "",
 +                    "city": "LOS ANGELES",
 +                    "region": "CA",
 +                    "postal_code": "90028",
 +                    "country": "US",
 +                    "phone": "",
 +                    "is_default_billing": false,
 +                    "is_default_shipping": true,
 +                    "date_created": null,
 +                    "date_modified": "2022-08-01T08:58:15-0700"
 +                }
 +            },
 +            "id": 12345678,
 +            "last_login_date": "2022-07-29T04:10:03-0700",
 +            "first_name": "John",
 +            "last_name": "Person",
 +            "email": "john@example.com",
 +            "tax_id": "",
 +            "password_salt": "",
 +            "password_hash": "$P$Bfo4kbFOqal4gqR9RcE/xg2lK75zK1",
 +            "password_hash_type": "phpass",
 +            "password_hash_config": "8",
 +            "forgot_password": "",
 +            "forgot_password_timestamp": null,
 +            "is_anonymous": false,
 +            "date_created": null,
 +            "date_modified": "2022-08-01T08:58:15-0700"
 +        },
 +        "fx:transaction_template": {
 +            "_links": { },
 +            "_embedded": {
 +                "fx:items": [
 +                    {
 +                        "_links": { },
 +                        "_embedded": {
 +                            "fx:item_options": [
 +                                {
 +                                    "_links": { },
 +                                    "name": "size",
 +                                    "value": "Large",
 +                                    "price_mod": 0,
 +                                    "weight_mod": 0,
 +                                    "date_created": null,
 +                                    "date_modified": null
 +                                },
 +                                {
 +                                    "_links": { },
 +                                    "name": "color",
 +                                    "value": "Surprise Me",
 +                                    "price_mod": 0,
 +                                    "weight_mod": 0,
 +                                    "date_created": null,
 +                                    "date_modified": null
 +                                }
 +                            ],
 +                            "fx:item_category": {
 +                                "_links": { },
 +                                "admin_email_template_uri": "",
 +                                "customer_email_template_uri": "",
 +                                "gift_recipient_email_template_uri": "https://api.foxycart.com/email_templates/1234",
 +                                "code": "DEFAULT",
 +                                "name": "Default for all products",
 +                                "item_delivery_type": "flat_rate",
 +                                "max_downloads_per_customer": 3,
 +                                "max_downloads_time_period": 24,
 +                                "default_weight": 1,
 +                                "default_weight_unit": "LBS",
 +                                "default_length_unit": "IN",
 +                                "shipping_flat_rate_type": "per_order",
 +                                "shipping_flat_rate": 5,
 +                                "handling_fee_type": "flat_percent_with_minimum",
 +                                "handling_fee": 1,
 +                                "handling_fee_minimum": 0,
 +                                "handling_fee_percentage": 10,
 +                                "customs_value": 0,
 +                                "discount_type": "",
 +                                "discount_name": "Gift Set",
 +                                "discount_details": "single|3-9.98|5-19.96",
 +                                "send_customer_email": false,
 +                                "send_admin_email": false,
 +                                "admin_email": "",
 +                                "date_created": null,
 +                                "date_modified": "2022-07-28T01:44:56-0700"
 +                            }
 +                        },
 +                        "item_category_uri": "https://api.foxycart.com/item_categories/1234",
 +                        "name": "My Subscription",
 +                        "price": 24.99,
 +                        "quantity": 1,
 +                        "quantity_min": 0,
 +                        "quantity_max": 0,
 +                        "weight": 1,
 +                        "code": "mysub",
 +                        "parent_code": "",
 +                        "discount_name": "",
 +                        "discount_type": "",
 +                        "discount_details": "",
 +                        "subscription_frequency": "1m",
 +                        "subscription_start_date": "2022-08-01T00:00:00-0700",
 +                        "subscription_next_transaction_date": "2022-09-01T00:00:00-0700",
 +                        "subscription_end_date": null,
 +                        "is_future_line_item": false,
 +                        "shipto": "Me",
 +                        "url": "",
 +                        "image": "",
 +                        "length": 0,
 +                        "width": 0,
 +                        "height": 0,
 +                        "expires": 0,
 +                        "date_created": null,
 +                        "date_modified": "2022-08-01T08:58:16-0700"
 +                    }
 +                ],
 +                "fx:custom_fields": [
 +                    {
 +                        "_links": { },
 +                        "name": "newsletter_subscribe",
 +                        "value": "1",
 +                        "is_hidden": false,
 +                        "date_created": "2022-08-01T08:58:16-0700",
 +                        "date_modified": "2022-08-01T08:58:16-0700"
 +                    }
 +                ],
 +                "fx:discounts": [
 +                    {
 +                        "_links": { },
 +                        "code": "mycode",
 +                        "amount": -2.5,
 +                        "name": "My Coupon",
 +                        "display": "-$2.50",
 +                        "is_taxable": false,
 +                        "is_future_discount": false,
 +                        "date_created": "2022-08-01T08:58:16-0700",
 +                        "date_modified": "2022-08-01T08:58:16-0700"
 +                    }
 +                ]
 +            },
 +            "customer_uri": "https://api.foxycart.com/customers/12345678",
 +            "template_set_uri": "https://api.foxycart.com/template_sets/1234",
 +            "payment_method_uri": "",
 +            "language": "",
 +            "locale_code": "en_US",
 +            "use_customer_shipping_address": false,
 +            "billing_first_name": "John",
 +            "billing_last_name": "Person",
 +            "billing_company": "",
 +            "billing_address1": "123 Testing Street",
 +            "billing_address2": "",
 +            "billing_city": "LOS ANGELES",
 +            "billing_state": "CA",
 +            "billing_postal_code": "90028",
 +            "billing_country": "US",
 +            "billing_phone": "",
 +            "customer_email": "john@example.com",
 +            "shipping_first_name": "John",
 +            "shipping_last_name": "Person",
 +            "shipping_company": "",
 +            "shipping_address1": "123 Testing Street",
 +            "shipping_address2": "",
 +            "shipping_city": "LOS ANGELES",
 +            "shipping_state": "CA",
 +            "shipping_postal_code": "90028",
 +            "shipping_country": "US",
 +            "shipping_phone": "",
 +            "total_item_price": 24.99,
 +            "total_tax": 0,
 +            "total_shipping": 7.5,
 +            "total_future_shipping": 0,
 +            "total_order": 29.99,
 +            "date_created": null,
 +            "date_modified": "2022-08-01T08:58:16-0700",
 +            "currency_code": "USD",
 +            "currency_symbol": "$"
 +        }
 +    },
 +    "start_date": "2022-08-01T00:00:00-0700",
 +    "next_transaction_date": "2022-09-01T00:00:00-0700",
 +    "end_date": null,
 +    "frequency": "1m",
 +    "error_message": "",
 +    "past_due_amount": 0,
 +    "first_failed_transaction_date": null,
 +    "is_active": true,
 +    "third_party_id": "",
 +    "cancellation_source": "",
 +    "date_created": "2022-08-01T08:58:16-0700",
 +    "date_modified": "2022-08-01T08:58:16-0700",
 +    "payment_type": "plastic"
 +}</code>
 +
 +
 +=== Customer ===
 +
 +<code javascript>{
 +    "_links": { },
 +    "_embedded": {
 +        "fx:attributes": [
 +            {
 +                "_links": { },
 +                "name": "Loyalty Points",
 +                "value": "100",
 +                "visibility": "private",
 +                "date_created": "2020-09-18T08:39:22-0700",
 +                "date_modified": "2020-09-18T08:39:22-0700"
 +            },
 +            {
 +                "_links": { },
 +                "name": "Level",
 +                "value": "Bronze",
 +                "visibility": "public",
 +                "date_created": "2020-09-18T08:40:53-0700",
 +                "date_modified": "2020-09-18T08:40:53-0700"
 +            },
 +            {
 +                "_links": { },
 +                "name": "Loyalty_Level",
 +                "value": "Blue",
 +                "visibility": "public",
 +                "date_created": "2021-05-17T03:43:36-0700",
 +                "date_modified": "2021-05-17T03:43:36-0700"
 +            }
 +        ],
 +        "fx:default_billing_address": {
 +            "_links": { },
 +            "address_name": "Default Billing Address",
 +            "first_name": "John",
 +            "last_name": "Person",
 +            "company": "",
 +            "address1": "123 Testing Street",
 +            "address2": "",
 +            "city": "LOS ANGELES",
 +            "region": "CA",
 +            "postal_code": "90028",
 +            "country": "US",
 +            "phone": "",
 +            "is_default_billing": true,
 +            "is_default_shipping": false,
 +            "date_created": null,
 +            "date_modified": "2022-08-01T08:58:15-0700"
 +        },
 +        "fx:default_shipping_address": {
 +            "_links": { },
 +            "address_name": "Me",
 +            "first_name": "John",
 +            "last_name": "Person",
 +            "company": "",
 +            "address1": "123 Testing Street",
 +            "address2": "",
 +            "city": "LOS ANGELES",
 +            "region": "CA",
 +            "postal_code": "90028",
 +            "country": "US",
 +            "phone": "",
 +            "is_default_billing": false,
 +            "is_default_shipping": true,
 +            "date_created": null,
 +            "date_modified": "2022-08-01T08:58:15-0700"
 +        },
 +        "fx:default_payment_method": {
 +            "_links": { },
 +            "save_cc": true,
 +            "cc_type": "Visa",
 +            "cc_number_masked": "xxxxxxxxx4242",
 +            "cc_exp_month": "01",
 +            "cc_exp_year": "2023",
 +            "date_created": null,
 +            "date_modified": "2022-08-01T08:58:15-0700"
 +        },
 +        "fx:customer_addresses": [
 +            {
 +                "_links": { },
 +                "address_name": "Work",
 +                "first_name": "John",
 +                "last_name": "Person",
 +                "company": "",
 +                "address1": "1024 Commercial Road",
 +                "address2": "",
 +                "city": "LOS ANGELES",
 +                "region": "CA",
 +                "postal_code": "90028",
 +                "country": "US",
 +                "phone": "",
 +                "is_default_billing": false,
 +                "is_default_shipping": false,
 +                "date_created": "2014-09-16T04:21:31-0700",
 +                "date_modified": "2014-10-06T20:00:17-0700"
 +            },
 +            {
 +                "_links": { },
 +                "address_name": "Mum",
 +                "first_name": "Jane",
 +                "last_name": "Person",
 +                "company": "",
 +                "address1": "88 High Street",
 +                "address2": "",
 +                "city": "NEW YORK",
 +                "region": "NY",
 +                "postal_code": "10001",
 +                "country": "US",
 +                "phone": "",
 +                "is_default_billing": false,
 +                "is_default_shipping": false,
 +                "date_created": "2014-10-14T19:12:17-0700",
 +                "date_modified": "2022-01-17T09:02:48-0800"
 +            }
 +        ]
 +    },
 +    "id": 12345678,
 +    "last_login_date": "2022-07-29T04:10:03-0700",
 +    "first_name": "John",
 +    "last_name": "Person",
 +    "email": "john@example.com",
 +    "tax_id": "",
 +    "password_salt": "",
 +    "password_hash": "$P$Bfo4kbFOqal4gqR9RcE/xg2lK75zK1",
 +    "password_hash_type": "phpass",
 +    "password_hash_config": "8",
 +    "forgot_password": "",
 +    "forgot_password_timestamp": null,
 +    "is_anonymous": false,
 +    "date_created": null,
 +    "date_modified": "2022-08-01T08:58:15-0700"
 +}</code>
 +
 +
 +====== JSON Webhook (Legacy) ======
 +
 +The following information is for our legacy webhook functionality. If you're creating a new webhook, you'll use the new version documented above.
  
 ===== Creating a webhook ===== ===== Creating a webhook =====
Line 105: Line 894:
 ==== Webhook Events ==== ==== Webhook Events ====
  
-JSON webhooks can be triggered for different events that occur in your store, selected when creating or editing the webhook. Currently we support two events, with more to come in the future.+JSON webhooks can be triggered for different events that occur in your store, selected when creating or editing the webhook. Currently we support events on transactions and subscriptions, with more to come in the future.
  
 === Transaction Created === === Transaction Created ===
 The Transaction Created webhook option receives any transaction for the store, whether it's a new transaction, a subscription renewal, an update of customer info, or a customer-initiated subscription cancel (technically, when a subscription end date is set – always a future date). Those all generate a transaction in the system, so are fed to the endpoint. The Transaction Created webhook option receives any transaction for the store, whether it's a new transaction, a subscription renewal, an update of customer info, or a customer-initiated subscription cancel (technically, when a subscription end date is set – always a future date). Those all generate a transaction in the system, so are fed to the endpoint.
 +
 +=== Transaction Captured/Refunded/Voided ===
 +
 +<wrap hi>This currently relies on beta transaction editing functionality that is manually enabled on a per store basis.</wrap>
 +
 +The three events for Captured, Refunded and Voided occur when an existing transaction is either manually captured, refunded or voided. This can be triggered either through the transaction report section of the Foxy administration, or through [[https://api.foxycart.com|the API]]. Note that the Captured event here is for a previously uncaptured transaction that was either verified or authorized that is then manually captured. 
 +
 +The original transaction (whether it was fully captured, or only authorized or verified) would have triggered the Transaction Created event at that time. The Captured, Refunded or Voided event is then in relation to the change of the payment status for the transaction.
  
 === Subscription Cancelled === === Subscription Cancelled ===
Line 114: Line 911:
 The Subscription Cancelled event occurs when a subscription is actually ended, on the end date set on the subscription. The Subscription Cancelled event occurs when a subscription is actually ended, on the end date set on the subscription.
  
-Subscriptions that are made inactive directly via the administration or the API **do not** trigger this event. Customers completing a ''sub_cancel'' checkout type also don't trigger this event, they trigger a Transaction Created webhook instead, with a ''transaction_type'' attribute in the payload of ''subscription_cancellation''+Subscriptions that are made inactive directly via the administration or the API **do not** trigger this event. Customers completing a ''sub_cancel'' checkout type also don't trigger this event, as the ''sub_cancel'' sets the subscriptions end date to either tomorrow or the next transaction date (depending on the store settings). A ''sub_cancel'' checkout will trigger a Transaction Created webhook instead, with a ''transaction_type'' attribute in the payload of ''subscription_cancellation'', and the new ''subscription_end_date'' set on the subscription product.
 ===== Testing Webhooks: Helpful Tips ===== ===== Testing Webhooks: Helpful Tips =====
  
Line 128: Line 925:
  
 ^ Header ^ Description ^ ^ Header ^ Description ^
-| ''Foxy-Webhook-Event'' | Name of the event that triggered this payload. Currently ''transaction/created'' and ''subscription/cancelled''. |+| ''Foxy-Webhook-Event'' | Name of the event that triggered this payload. Currently ''transaction/created'', ''transaction/captured'', ''transaction/refunded'', ''transaction/voided'', ''subscription/cancelled''. |
 | ''Foxy-Webhook-Signature'' | A HMAC SHA256 signature of the payload, using the webhook's encryption key. Used for verifying the contents of the payload. | | ''Foxy-Webhook-Signature'' | A HMAC SHA256 signature of the payload, using the webhook's encryption key. Used for verifying the contents of the payload. |
 | ''Foxy-Webhook-Refeed'' | A boolean to signify if this payload has been refed. If ''false'', then this is the first time this specific instance of the event has been triggered. | | ''Foxy-Webhook-Refeed'' | A boolean to signify if this payload has been refed. If ''false'', then this is the first time this specific instance of the event has been triggered. |
Line 441: Line 1238:
     },     },
     "_links": { },     "_links": { },
-    "currency": "USD",+    "currency_code": "USD", 
 +    "currency_symbol": "$",
     "customer_email": "john@example.com",     "customer_email": "john@example.com",
     "customer_first_name": "John",     "customer_first_name": "John",
Line 470: Line 1268:
     "transaction_date": "2018-03-01T00:00:00-0700",     "transaction_date": "2018-03-01T00:00:00-0700",
     "transaction_type": "transaction"     "transaction_type": "transaction"
 +    "user_agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0"
 }</code> }</code>
  
Line 692: Line 1491:
     return;     return;
 } }
 +</code>
 +
 +=== Node ===
 +
 +Note that you can also use the official [[https://github.com/Foxy/foxy-sdk|Foxy SDK]] to make pieces of this easier, but this example involves minimal dependencies: 
 +<code javascript>
 +const crypto = require('crypto');
 +const foxyEncryptionKey = 'YOUR_ENCRYPTION_KEY_HERE';
 +const foxyStoreId = 'YOUR_STORE_ID_HERE';
 +const foxyStoreDomain = 'YOUR_STORE_DOMAIN_HERE';
 +
 +const http = require('http');
 +const server = http.createServer(handleRequest);
 +
 +const routes = {
 +  'transaction/created': handleTransactionCreated,
 +}
 +
 +function handleRequest(request, response) {
 +  if (!validFoxyRequest(request)) {
 +    response.statusCode = 403; // Forbidden
 +    response.write('Forbidden');
 +    return response.end();
 +  }
 +  const bodyChunks = [];
 +
 +  request.on('data', (chunk) => bodyChunks.push(chunk));
 +  request.on('end', () => {
 +    let body = Buffer.concat(bodyChunks).toString()
 +    if (!validFoxySignature(request.headers['foxy-webhook-signature'], body)){
 +      response.statusCode = 403; // Forbidden
 +      response.write('Forbidden');
 +      return response.end();
 +    }
 +    try {
 +      body = JSON.parse(body);
 +    } catch(e) {
 +      response.statusCode = 400; // Bad Request
 +      response.write('Bad Request');
 +      return response.end();
 +    }
 +    const foxyEvent = request.headers['foxy-webhook-event'];
 +    const responseData = routes[foxyEvent](request.headers, body);
 +    console.log(responseData);
 +    if (responseData) {
 +      response.statusCode = 200;
 +      response.write(JSON.stringify(responseData));
 +      return response.end();
 +    }
 +    response.statusCode = 500;
 +    response.end();
 +  });
 +}
 +
 +function validFoxyRequest(request) {
 +  const postMethod = request.method === 'POST';
 +  const headers = request.headers;
 +  const routeForEventExists = Object.keys(routes).includes(headers['foxy-webhook-event']);
 +  const foxySignatureExists = !!headers['foxy-webhook-signature'];
 +  const foxyStoreIdIsCorrect = headers['foxy-store-id'] === foxyStoreId;
 +  const foxyStoreDomainIsCorrect = headers['foxy-store-domain'] === foxyStoreDomain;
 +  return postMethod && routeForEventExists && foxySignatureExists && foxyStoreIdIsCorrect && foxyStoreDomainIsCorrect;
 +}
 +
 +function validFoxySignature(signature, payload) {
 +  const referenceSignature = crypto.createHmac('sha256', foxyEncryptionKey).update(payload).digest('hex');
 +  console.log(referenceSignature);
 +  return signature === referenceSignature;
 +}
 +
 +function handleTransactionCreated(headers, body) {
 +  const emailAddress = body['customer_email'];
 +  const billingCountry = body['_embedded']['fx:billing_addresses']['country'];
 +  const shippingCountry = body['_embedded']['fx:shipments'][0]['country'];
 +  // Check if there is a Product A and its size
 +  let hasSmallA = false;;
 +  let hasLargeA = false;;
 +  for (let item of body['_embedded']['fx:items']) {
 +    const name = item['name'];
 +    const quantity = item['quantity'];
 +    const category = item['_embedded']['fx:item_category']['code'];
 +    if(item['name'] === "Product A") {
 +      for (let itemOption of item['_embedded']['fx:item_options']) {
 +        if (itemOption['name'] == 'size') {
 +          if (itemOption['value'] === 'small') {
 +            hasSmallA = true;
 +            return {
 +              ok: true,
 +              details: "has small A"
 +            }
 +          } else if (itemOption['value'] === 'large') {
 +            hasLargeA = true;
 +            return {
 +              ok: true,
 +              details: "has large A"
 +            }
 +          }
 +        }
 +      }
 +    }
 +  }
 +}
 +
 +server.listen(80);
 </code> </code>
  
Line 794: Line 1697:
 </code> </code>
  
-====== Legacy XML Webhook ====== 
- 
-The Legacy XML Webhook matches our previous XML datafeed functionality, and shouldn't be used for any brand new integrations - but can be useful for connecting to existing endpoints/integrations which were built against our datafeed functionality. For details on how to accept and process the XML payload, you can review [[.:transaction_xml_datafeed|the existing documentation here]]. 
- 
-The only new functionality that the Webhooks version introduces beyond the documentation linked above is the ability to specify multiple endpoints from the "Integrations" section of the FoxyCart administration, and the automatic retries after failures. The API key used to decrypt the datafeed is still the key detailed on the "Advanced" settings page in the administration. 
  
 ====== Zapier ====== ====== Zapier ======
Line 822: Line 1720:
 Before connecting Foxy to your Webflow site - you first need to create the necessary product collection within the Webflow CMS. For details on how to create collections - you can [[https://university.webflow.com/article/cms-collections|follow Webflow's guide on that here]]. Before connecting Foxy to your Webflow site - you first need to create the necessary product collection within the Webflow CMS. For details on how to create collections - you can [[https://university.webflow.com/article/cms-collections|follow Webflow's guide on that here]].
  
-We also have a tutorial and starter template available for building a responsive ecommerce website with Webflow and Foxy - [[https://www.foxy.io/tutorials/webflow-build-a-responsive-online-store|which you can review here]]. The tutorial and template will get you set up with a starting collection and templates ready to go for this integration.+We also have tutorials and starter template available for building a responsive ecommerce website with Webflow and Foxy - [[https://support.foxy.io/webflow/getting-started-with-foxy-webflow|which you can review here]]. The information there will help you get you set up and ready to go for this integration.
  
 If you're creating your own collections, when creating the Webflow collection for your products - there are some options you'll need as a minimum to work with Foxy, and we would recommend setting all of these options to also be required fields for creating products. If you're creating your own collections, when creating the Webflow collection for your products - there are some options you'll need as a minimum to work with Foxy, and we would recommend setting all of these options to also be required fields for creating products.
Line 871: Line 1769:
  
 Beyond the [[#handling_failed_webhooks|webhook errors noted earlier on this page]], there are also errors specific to the Webflow integration that you may experience. Beyond the [[#handling_failed_webhooks|webhook errors noted earlier on this page]], there are also errors specific to the Webflow integration that you may experience.
 +
 +==== Product code ... not found ====
  
 Specifically, if you have a product in a transaction which is missing a code attribute, or has a code attribute set which doesn't match an item in your products collection, you'll see an error like this within your store's error log: Specifically, if you have a product in a transaction which is missing a code attribute, or has a code attribute set which doesn't match an item in your products collection, you'll see an error like this within your store's error log:
Line 880: Line 1780:
  
 If you experience this error, you'll first want to confirm where the product was added to the cart and ensure that the link/form has the correct code associated with the product. To be able to re-feed the webhook to Webflow, you will need to update the product in the CMS to have the matching code to how it was sent. If you experience this error, you'll first want to confirm where the product was added to the cart and ensure that the link/form has the correct code associated with the product. To be able to re-feed the webhook to Webflow, you will need to update the product in the CMS to have the matching code to how it was sent.
 +
 +If the product code in the transaction matches the product in your collection, you will also want to confirm that the configured settings for your Webflow connection on the "Integrations" page in the Foxy administration is set to the correct field from your collection for the code. For example, if you're using the ''slug'' field from your collection as the product code, then that should also be set in the same way on the "Integrations" page in the Foxy admin. If it's not correct, you will need to disable the connection and re-connect, ensuring you select the right fields from your collection.
 +
 +==== This item can't be published / CollectionSchemaChangedError ====
  
 If you've edited your product collections schema without publishing the page, Webflow will prevent any publishing requests via the API until the changes are published. If you experience this error, you'll see an error like this within your store's error log: If you've edited your product collections schema without publishing the page, Webflow will prevent any publishing requests via the API until the changes are published. If you experience this error, you'll see an error like this within your store's error log:
Line 886: Line 1790:
 Webhooks processing problems: Webhooks processing problems:
 Your Site Name (webflow): Conflict: This item can't be published, as your Collection structure changed since the last site publish. Make sure your staging and live Collections match to continue. Your Site Name (webflow): Conflict: This item can't be published, as your Collection structure changed since the last site publish. Make sure your staging and live Collections match to continue.
 +</code>
 +<code>
 +Webhooks processing problems:
 +Webflow (webflow): CollectionSchemaChangedError: The collection structure changed since the last publish [400]
 </code> </code>
  
-To fix this, simply ensure any changes to your collection's schemas have been published within Webflow, and then refeed the webhook to your Webflow site.+To fix these types of errors, simply ensure any changes to your collection's schemas have been published within Webflow, and then refeed the webhook to your Webflow site.

Site Tools