For advanced integration and tracking options FastSpring provides "events" which are delivered by "webhooks" and available via the FastSpring API.
There are two types of webhooks available: server webhooks and browser scripts.
- Server webhooks post JSON data from FastSpring's back-end to one or more external URLs or endpoints specified by you. You can write scripts to parse the data and update your databases or trigger other events based on the contents of the data.
You can have multiple webhooks, and each type of webhook event can be sent to as many different URLs as you need.
Setting Up Webhooks
To set up webhooks, login to the Dashboard and select the Integrations menu.
Then, select the Webhooks tab. An empty webhook container (for both live and test events) is created for you automatically, but you can click to create additional webhooks if needed.
Adding a Server Webhook
- Click ADD WEBHOOK URL. The Add Webhook URL popup dialog will appear.
- In the URL field, enter the external URL or endpoint where JSON data will be posted. We strongly recommend that you use HTTPS endpoints so that data will be encrypted against interception.
- In the HMAC SHA256 Secret field, you can optionally enter a secret phrase for creating a digest of the payload to provide an additional layer of security. See Message Secret / Security for more details.
- In the Events section, select the check box for each event that you want posted to the URL or endpoint for this webhook.
- Scroll down to the bottom of the dialog (if necessary) and click ADD.
Adding a Browser Script
- Click ADD BROWSER SCRIPT. The Add Browser Script popup dialog will appear.
- In the Name field, optionally enter an internal name for the script that will help you identify it if you create more than one for this webhook.
- In the Events section, select browser.order.completed.
- Click ADD.
Creating Additional Webhooks and Editing Existing Webhooks
- If you click to create an additional webhook, or if you click EDIT in a webhook container (next to ADD BROWSER SCRIPT), a window similar to the following will appear.
- The optional Title field is for internal use and helps you to distinguish (in addition to the URL) between one webhook and another.
- By default, Get webhooks from is set to send webhook events for both Live and Test Orders. If you only wants events to be sent via this webhook for for live orders - or only for test orders - click the drop-down and select the desired option.
- If you want this webhook to use expanded JSON data (e.g. to include full account details in an order.completed post), select Enable webhook expansion. (More information about expansion is available directly below.)
- Click ADD to add a new webhook, or SAVE to save your changes.
About Webhook Expansion
Depending on the type of event being posted, only data relevant to that event type will be included by default. For example, in an order.completed event, the customer's account ID will be included by default, but not the remainder of the account details. Those will be included in a separate account.created webhook event.
However, if you select Enable webhook expansion, then the objects listed below will be fully expanded / include all data in events other than their own event types. To continue the example above, with this option enabled, order.completed will include the customer's complete account object rather than just the account ID. Depending upon your implementation, this may obviate the need to subscribe to certain webhooks (e.g. account.created), or to make API calls to fill in certain details.
Expandable Webhook Event Objects
Viewing Recent Server Webhook Activity
The Webhooks tab of the Integrations menu includes a RECENT ACTIVITY command towards the bottom right-hand corner of the page, which lets you view all recent server wehbook on demand, right in your browser window.
Clicking RECENT ACTIVITY opens a scrollable popup window that shows those only recent events for which you have configured server webhooks, along with the contents of the posts that were sent to your specified URL(s).
If you believe that you may have missed receiving one or more recent server webhooks (e.g., due to temporary unavailability of your server), you can also use the /events/unprocessed endpoint of the FastSpring API to request the contents of any recent server webhooks that were not delivered successfully. The response structure will be identical to that of the webhooks. See Retrieving Missed or Unprocessed Events below.
Server-to-server "webhooks" are delivered as the POST body JSON payload to the URL(s) specified while setting up the webhook(s). Upon firing, some webhooks also trigger an email message to the customer, depending on the context.
|Event Name||Description||Email Message Sent|
|account.created||Fired when a customer account is created (e.g. when a customer whose email address does not match an existing account places a new order). Customer Accounts and single sign-on provides detailed information regarding customer accounts.|
|fulfillment.failed||Fired if one or more fulfillments failed during order fulfillment (e.g. due to insufficient remaining licenses in a pre-generated list).|
|mailingListEntry.removed||Fired when an entry is expected to be removed from a mailing list (e.g. due to customer unsubscribing by placing an order with the newsletter check box cleared / unselected). Please see Cart Abandonment Tracking and Customer Mailing List Opt-In for more information.|
|mailingListEntry.updated||Fired upon adding a new mailing list entry (e.g. for a customer who completed an order and selected the check box to "subscribe to news and updates"). Please see Cart Abandonment Tracking and Customer Mailing List Opt-In for more information.|
|order.approval.pending||Fired when approval is required before an order can be completed (for example, when purchase orders are enabled for your Store with the Require Approval method configured, and a buyer places an order using a purchase order).||Order Pending Approval|
|order.canceled||Fired when an order is canceled (e.g. when you cancel a pending approval order via the Dashboard).|
|order.payment.pending||Fired when an order has been processed but payment from the buyer has not yet been completed (for example, when a buyer selects wire transfer as their payment method or buys using a purchase order).||Payment Required for the Order|
Fired upon successful order completion after fulfillment actions have been performed.
For subscriptions, this event is only fired for the initial purchase transaction. Subsequent subscription billings do not trigger this event; only subscription.charge.completed events will be triggered.
|Default Order Receipt|
|order.failed||Fired if an order failed during checkout (e.g. due to a declined payment card).|
|payoutEntry.created||Fired when a payout event has been created (e.g. for an order, split pay rule, return etc.).|
|return.created||Fired when a refund or a return has been created (e.g. by returning a customer's order via the Dashboard).|
|subscription.activated||Fired upon creation of a new subscription.||Activated|
|subscription.canceled||Fired upon cancellation of the subscription, when the Deactivate At Next Period option has been selected (if canceling via Dashboard) or the billingPeriod=0 parameter has not been included (if canceling via the /subscriptions endpoint of the FastSpring API).||Canceled|
Fired upon completion of a recurring or managed subscription charge, or a charge resulting from proration following a subscription upgrade or downgrade.
This event is not fired for the initial purchase of a subscription. Instead, we send order.completed - which is only fired for new purchases (including the initial purchase of a subscription) - and subscription.activated .
|subscription.charge.failed||Fired when a subscription charge or billing has failed (e.g. due to a declined payment card transaction).||Charge Failed|
|subscription.deactivated||Fired upon deactivation of the subscription, including deactivation at the end of the billing period following a prior cancellation, or immediately upon cancellation when the subscription is canceled with the Deactivate Now option selected (via Dashboard) or the billingPeriod=0 parameter is included (canceling via the /subscriptions endpoint of the FastSpring API).||Deactivated|
|subscription.payment.overdue||Fired upon the overdue interval following the payment failed date.||Payment Overdue|
|subscription.payment.reminder||Fired upon the reminder interval before the next charge date.||Payment Reminder|
|subscription.trial.reminder||Fired when an email message is sent to the customer prior to the first billing, following a free trial period as configured via the Free Trial Days field in the Pricing popup dialog of the Dashboard, or via the trial field inside the pricing node of a POST to the /products endpoint of the FastSpring API.||Trial Reminder|
|subscription.updated||Fired when edits have been made to a subscription instance (e.g. by modifying the product, next payment date, etc. via Dashboard or the /subscriptions endpoint of the FastSpring API).||Updated|
Your webhooks endpoint should be able to receive 1 or more event. During setup you'll define which types of events a given URL receives. Multiple webhooks might be combined in a single payload.
This is an example request your endpoint would receive containing two different event types:
Common fields for all types of events
"id" - Unique ID of the event.
"live" - Whether this event is for live data instead of test data.
"processed" - Whether this event has been marked processed. For a new event this will always be false.
"type" - Identifier for the event that occurred.
"created" - Timestamp for when the event was created.
"data" - Varies per event "type". See Webhook Payload Examples for "data" contents.
Marking Events as Processed
The goal of a Webhook is to mark received events as processed. There are two techniques:
- Bulk. Return HTTP status code 200 to consider all events received as successfully processed.
- Individual. Return HTTP status code 202 to exert more control over what is considered processed. In the response body, emit one event "id" on each new line (separated by character 10). Each event "id" given will be considered successfully processed.
All other HTTP status codes are considered failures. However, for failures, we recommend returning status codes in the 50X range, depending on the cause of the failure.
Retrieving Missed or Unprocessed Events
In the event that your server does not process one or more events successfully (e.g. if your server is temporarily unavailable at the time an event is posted), you can repost them manually via the order or subscription details page, OR retrieve any and all missed events by making a call to the /events/unprocessed endpoint of the FastSpring API.
Simply make a GET call to /events/unprocessed endpoint and all subscribed webhook events that have not been marked as processed (see above) will be returned in the API response. The response structure will be identical to the structures of the unprocessed webhook events, so you can process the response in the same way you would have processed the corresponding / missed webhook posts.
Message Secret / Security
Each webhook can optionally define a secret cryptographic key in the HMAC SHA256 Secret field. FastSpring's server will use that key to generate a hashed digest of each webhook payload. The resulting digest will be encoded to base64 and included in the webhook's X-FS-Signature header. Your server can then use the same process, creating a hashed digest of the payload using the same secret key on your side, and then encoding the resulting hash to base64 before comparing the it to the value in that header.
A post with a valid, matching digest in the header can only have originated from a source that uses the correct secret key. Therefore, if you have only provided the secret key to FastSpring via the webhook interface in Dashboard (i.e., you have not given the key to anyone else or used it anywhere else), this confirms that the webhook data is authentic (and also intact), since nobody else knows your secret key and the key is not (of course) included in the post. You can find more information about hash-based message authentication at https://en.wikipedia.org/wiki/Hash-based_message_authentication_code.
The following is an example of using the PHP hash_hmac function to create the hashed digest, where $secret is the secret key entered in the HMAC SHA256 Secret field in Dashboard, and $whole_fs_json_payload is the raw data from the webhook post:
BROWSER.ORDER.COMPLETED - fired upon successful order completion after fulfillment actions were performed.
Loading External Scripts
It's common to require external scripts for the hook. To load external scripts use the following approach within the function: