Web Hooks, Service Hooks, and Captain Hooks


  1. Overview
  2. Hook-able Events
    1. New Subscription
    2. Subscription Changed
    3. Subscription Canceled
    4. Subscription Reactivated
    5. Customer Deleted
    6. Transaction
    7. Subscription Billable
    8. Bill Reminder
  3. Custom URLs (Web Hooks)
    1. Data Format and Definition
      1. Data Common To All Hooks
      2. Hook-Specific Supplemental Data
        1. Subscription Changed
    2. Security
      1. SSL
      2. Request Signature Verification
        1. Ruby Example
        2. PHP Raw Example
        3. PHP Zend Framework Controller Example
        4. C# Example
      3. X-CG-Token Header
      4. Restrict By IP
    3. Testing
  4. Third Party Apps (Service Hooks)
    1. Zapier
    2. Campaign Monitor
  5. Fault Tolerance, Retries, and Reporting
    1. Affirmative Response
      1. Timeouts
    2. Automatic Retries
      1. Idempotence
    3. Manual Retries and Canceling Retries

1. Overview

Cheddar provides web hook functionality to greatly increase the capabilities of the platform. Web hooks, also known as "service hooks", also known as "reverse API", also known as "callbacks", also known as "silent postbacks" are messages sent by Cheddar to external services. Web hooks are triggered by various events within Cheddar. There are two general types: Custom URLs and Third Party Apps.

Web hook functionality is included with all Cheddar service levels. No additional fees apply. Some hooks may require a third-party account.

2. Events

Many events occur within Cheddar as a natural part of performing its duties. Below is a list of events which are "actionable" via the Service Hooks system.

2.1 New Subscription

A New Subscription event occurs when a new customer is created in Cheddar. This could occur via any one of several possible actions: API call, Admin GUI, Hosted Payment Create Page, etc.

2.2 Subscription Changed

This event occurs when a customer's subscribed pricing plan is changed.

2.3 Subscription Canceled

The Subscription Canceled event occurs upon any cancelation. Cancelations can occur automatically as a result of non-payment, for example but also can be explicitly initiated via the API or GUI.

2.4 Subscription Reactivated

A Subscription Reactivated event occurs when a previously canceled subscription is successfully reactivated.

2.5 Customer Deleted

If a customer is deleted via the API or GUI, a Customer Deleted event occurs.

2.6 Transaction

The Transaction event is triggered by any transaction. A transaction could be for a recurring subscription invoice, one-time invoice, refund, or void. This event is triggered when any transaction is executed with any result. It is also triggered when a transaction is updated with settlement information (e.g., PayPal Echeck or normal ACH).

Differentiating the types of transactions is accomplished by examining the hook payload:

  • Refund: The subscription[invoice][transaction][parentId] will contain a value (the id of the refunded transaction) and the subscription[invoice][transaction][amount] will contain a negative value.
  • Void: The subscription[invoice][transaction][response] will have a value of "voided".
  • One-time Invoice: The subscription[invoice][type] will have a value of "one-time".
  • Recurring Invoice: The subscription[invoice][type] will have a value of "subscription".

For more information about the data your listener will receive from a Cheddar hook, see the data common to all hooks section below.

2.7 Subscription Billable

The Subscription Billable event is triggered by the recurring engine when an invoice becomes billable. If a hook is registered for the Subscription Billable event, the recurring engine will not execute the invoice immediately. Rather, the hook is sent which gives you (or more accurately your hook listener) the opportunity to execute arbitrary actions prior to transacting the invoice. Only after all Billable hooks are successfully processed by your listeners will the invoice be transacted. For more information, see the Invoice Review article.

2.8 Bill Reminder

The Bill Reminder event is triggered according to your settings.

3 Custom URLs (Web Hooks)

Web Hooks are standardized messages sent to any recipient for further action. Learn more about web hooks in general.

Cheddar provides the capability to send/receive customer/subscription/invoice/transaction data to any URL you choose. You may configure an unlimited number of "listeners" for web hooks.

Configure a Custom URL hook in Cheddar

3.1 Data Format and Definition

Data is sent in either application/x-www-form-urlencoded or application/json format (your choice!) to your listener via HTTP POST.

3.1.1 Data Common to All Hooks

Name Description
activityType The event type: newSubscription, subscriptionChanged, subscriptionCanceled, subscriptionReactivated, subscriptionBillable, customerDeleted, transaction
activityDatetime The moment the event occured in ISO 8601 format
activityActor The email address of the authenticated user who initiated the action, if any.
product[id] The custom code for the product account
product[code] Your custom code for the product account
product[name] The name of your product account
product[subdomain] Your subdomain, if any.
customer[id] Cheddar's unique id for the customer
customer[code] Your custom code for the customer
customer[key] Customer key hash (primarily for constructing a link to hosted update/status)
customer[gatewayToken] The gateway reference for this customer, if any
customer[firstName] Customer given name
customer[lastName] Customer family name
customer[email] Customer email address
customer[company] Customer's company
customer[notes] Notes regarding this customer
customer[isTaxExempt] Flag (1,0) indicating tax exemption status
customer[taxNumber] Customer's tax number, if any
customer[firstContactDatetime] The moment the customer first contacted you
customer[referer] The refering URI for the customer
customer[campaignSource] (utm_source)
customer[campaignMedium] (utm_medium)
customer[campaignTerm] (utm_term)
customer[campaignContent] (utm_content)
customer[campaignName] (utm_campaign)
customer[createdDatetime] The moment this customer was created in Cheddar
subscription[id] Cheddar's unique id for the subscription
subscription[gatewayToken] Gateway ref for this subscription, if any
subscription[method] The payment method type ('none', 'cc', 'paypal', or 'apple')
subscription[ccType] The credit card type, if any (visa, mc, disc, amex, diners, jcb)
subscription[ccLastFour] Last 4 digits of credit card, if any
subscription[ccFirstName] Billing first name (given)
subscription[ccLastName] Billing last name (family)
subscription[ccEmail] Billing email (paypal only)
subscription[ccExpirationDate] Payment method expiration date, if any
subscription[ccCompany] Billing company
subscription[ccCountry] Billing country
subscription[ccAddress] Billing address
subscription[canceledDatetime] The moment of cancelation, if any
subscription[cancelType] The cancel type, if any (unknown, declined, expired, paypal-wait, customer)
subscription[cancelReason] Description of reason for cancelation, if any
subscription[createdDatetime] Moment of subscription creation
subscription[plan][id] Cheddar's unique id for the plan
subscription[plan][code] Your custom code for the plan
subscription[plan][name] Plan name
subscription[plan][isActive] Flag (1,0) for the plan
subscription[plan][isFree] Flag (1,0) indicating whether or not the plan is free
subscription[plan][billingFrequencyUnit] (months, days, none)
subscription[plan][recurringChargeCode] Your code for the flat recurring charge
subscription[plan][recurringChargeAmount] Amount of the flat recurring charge
subscription[plan][setupChargeCode] Your code for the flat setup fee charge
subscription[plan][setupChargeAmount] The setup charge amount
subscription[plan][createdDatetime] The moment the plan was created
subscription[plan][items][<n>][id] Cheddar's unique id for the item
subscription[plan][items][<n>][code] Your custom code for the item
subscription[plan][items][<n>][name] Item name
subscription[plan][items][<n>][quantityIncluded] Quantity of the item included in the plan
subscription[plan][items][<n>][isPeriodic] Flag (1,0) indicating if Cheddar resets item quantity to zero to start a billing period
subscription[plan][items][<n>][overageAmount] The amount charged for overage, if any
subscription[invoice][id] Cheddar's unique id for the invoice
subscription[invoice][invoiceNumber] Invoice number sequence
subscription[invoice][type] Invoice type (subscription, setup, one-time)
subscription[invoice][billingDatetime] The billable moment for the invoice
subscription[invoice][previousBillingDatetime] The date and time of the last billable invoice if applicable. The billing period is between `billingDatetime` and `previousBillingDatetime`.
subscription[invoice][paidTransactionId] Cheddar's unique id for the transaction which "paid" this invoice
subscription[invoice][taxRate] Tax rate for this invoice
subscription[invoice][isInitial] Flag (1,0) indicating whether or not this is the initial recurring invoice
subscription[invoice][createdDatetime] The moment this invoice was created
subscription[invoice][items][<n>][id] Cheddar's unique id for the item
subscription[invoice][items][<n>][code] Your custom code for the item
subscription[invoice][items][<n>][name] Item name
subscription[invoice][items][<n>][quantity] The customer's quantity of this item as of the hook moment
subscription[invoice][charges][<n>][id] Cheddar's unique id for the charge
subscription[invoice][charges][<n>][code] Charge code for the charge
subscription[invoice][charges][<n>][type] Charge type (custom, setup, recurring, item)
subscription[invoice][charges][<n>][quantity] Charge quantity
subscription[invoice][charges][<n>][eachAmount] Charge amount for each quantity
subscription[invoice][charges][<n>][description] Charge description
subscription[invoice][charges][<n>][createdDatetime] Creation date of the charge
subscription[invoice][transaction][id] Cheddar's unique id for the transaction
subscription[invoice][transaction][parentId] Cheddar's unique id for the parent transaction, if any (if this is a refund)
subscription[invoice][transaction][gatewayToken] Gateway reference for this transaction
subscription[invoice][transaction][amount] Transaction amount (including tax, if any)
subscription[invoice][transaction][taxAmount] Amount of tax, if any
subscription[invoice][transaction][memo] Transaction memo
subscription[invoice][transaction][response] Transaction status (approved, declined, failed, error, voided)
subscription[invoice][transaction][responseReason] Description of the reason for the status
subscription[invoice][transaction][transactedDatetime] The moment this transaction was transacted

3.1.2 Hook-specific Supplemental Data Subscription Changed

The Subscription Changed hook includes the previous subscription information in addition to the data common to all hooks:

Name Description
previousSubscription[id] Cheddar's unique id for the subscription
previousSubscription[gatewayToken] Gateway ref for this subscription, if any
previousSubscription[ccType] The credit card type, if any (visa, mc, disc, amex, diners, jcb)
previousSubscription[ccLastFour] Last 4 digits of credit card, if any
previousSubscription[ccFirstName] Billing first name (given)
previousSubscription[ccLastName] Billing last name (family)
previousSubscription[ccEmail] Billing email (paypal only)
previousSubscription[ccExpirationDate] Payment method expiration date, if any
previousSubscription[ccCompany] Billing company
previousSubscription[ccCountry] Billing country
previousSubscription[ccAddress] Billing address
previousSubscription[canceledDatetime] The moment of cancelation, if any
previousSubscription[cancelType] The cancel type, if any (unknown, declined, expired, paypal-wait, customer)
previousSubscription[cancelReason] Description of reason for cancelation, if any
previousSubscription[createdDatetime] Moment of subscription creation
previousSubscription[plan][id] Cheddar's unique id for the plan
previousSubscription[plan][code] Your custom code for the plan
previousSubscription[plan][name] Plan name
previousSubscription[plan][isActive] Flag (1,0) for the plan
previousSubscription[plan][isFree] Flag (1,0) indicating whether or not the plan is free
previousSubscription[plan][billingFrequencyUnit] (months, days, none)
previousSubscription[plan][recurringChargeCode] Your code for the flat recurring charge
previousSubscription[plan][recurringChargeAmount] Amount of the flat recurring charge
previousSubscription[plan][setupChargeCode] Your code for the flat setup fee charge
previousSubscription[plan][setupChargeAmount] The setup charge amount
previousSubscription[plan][createdDatetime] The moment the plan was created
previousSubscription[plan][items][<n>][id] Cheddar's unique id for the item
previousSubscription[plan][items][<n>][code] Your custom code for the item
previousSubscription[plan][items][<n>][name] Item name
previousSubscription[plan][items][<n>][quantityIncluded] Quantity of the item included in the plan
previousSubscription[plan][items][<n>][isPeriodic] Flag (1,0) indicating if Cheddar resets item quantity to zero to start a billing period
previousSubscription[plan][items][<n>][overageAmount] The amount charged for overage, if any

3.2 Security

3.2.1 Use SSL

You may use a HTTP or a HTTPS url. HTTPS can be useful to protect your data or if you wish to protect against replay attacks for example.

3.2.2 Request Signature Verification

Hook requests are signed for additional security. You may wish to validate a request's signature to ensure that the hook is coming from Cheddar and is well formed. This is not a requirement but is highly recommended. HTTP POST requests from Cheddar's Custom URL hooks include a special header: X-CG-SIGNATURE. The value of this header is a HMAC sha256 keyed hex hash of an MD5 hash of the request body using your product secret key as the key. Exciting, right? Here are the generic steps to validate a request:

  1. Get the raw body of the request
    • This is the raw content of the HTTP POST request not including the headers
  2. Calculate the MD5 of the raw request body (we refer to this as the "request token")
    • The MD5 hash should be a 32-character hexadecimal number
  3. Use the sha256 algorithm to generate an HMAC hash of the request token
    • use your product secret key as the salt
    • The hash should result in a 64-character hexadecimal number
  4. Compare the result from step 3 to the value of the X-CG-SIGNATURE header in the request.
    • If they match, the request can be considered well-formed and from the expected source.

You can find your product secret key here. The key is called a secret key for a reason: it should be kept a secret. It is up to you to protect your secret key. A Ruby example for validating a request: A raw PHP example for validating a request:

Note that in PHP the super global $SERVER keys are the header names altered to be prepended with `HTTP` and dashes are underscores. http://support.cheddargetter.com/discussions/questions/1826-how-to-... A basic Zend Framework 1 controller for handling hooks: A basic C# example for validating a request:

3.2.3 X-CG-TOKEN Header

You may have noticed that there is also a X-CG-TOKEN header in hook requests. This header is provided as a convenience. It is the value of the request MD5 hash as calculated prior to request transit. This value should not be used in a production environment for validation of a request. It is provided so that you may compare it to your own calculation of the request hash while in development of your hook listener. Using the value of this header for validation rather than calculating the request token in your listener make a man-in-the-middle attack possible.

3.2.4 Restrict by IP

If you'd like to ensure that hooks are coming from Cheddar's IPs, you can do that, too. Currently Cheddar uses the following IPs. These are subject to change. If they do, you can be sure that you'll hear about it.


3.3 Testing

Just See a Post

One of the easiest ways to test a hook is using a basic POST receiver like PostCatcher or RequestBin. Setup a bin, configure the bin url in Cheddar, then cause an event to happen in your Cheddar account.

For a more robust solution, you might consider Runscope. With Runscope, you can receive and store all hooks and have them pass through to your app's listener. With the hook payloads stored in Runscope, you can search/troubleshoot old hook data. Believe me, it'll come in handy.

Rerunning Hooks

Often it's useful to trigger resending the same hook payload multiple times for development purposes. You can use the webhook management console to manually resend (or stop automatic retries) of individual events or events in bulk.

If you're using Runscope Gateway URLs, you can also rerun a hook using the Runscope interface, though those retries won't count against retry functionality in Cheddar.

Testing in Your Development Environment

Testing webhook functionality within your app in a development environment can be tricky especially if you develop on your local machine. Your webhook endpoint needs to be available on the public internet. Cheddar needs to send to a public location. This is where the various tunneling services come in. There're a few of those around. Check out Ngrok.

4 Third Party Apps (Service Hooks)

A Third Party App is an integration built into Cheddar using Cheddar's own event and hook management system.

4.1 Zapier

Zapier is like a web hook router. Zapier can accept any Cheddar hook event and redirect that data to any one (or more) of hundreds of other APIs out there.

Try out some of these examples:

4.2 Campaign Monitor

Campaign Monitor is email marketing software for designers and their clients.

When the Campaign Monitor hook is enabled, Cheddar will interact with your Campaign Monitor account in various ways. A new subscriber list is created and all existing customers are imported to the list. Then, as new customers signup, change plans, are canceled, reactivated or deleted, the subscriber list is updated accordingly.

Configure the Campaign Monitor hook in Cheddar

5 Fault Tolerance, Retries, and Reporting

Hooked Events are reported within the Admin GUI. A significant amount of information is available to you via this searchable interface. It doubles as a workspace for manipulating individual hooks or in bulk.

5.1 Affirmative Response

Your hook listener must respond with an HTTP status of 200-299. If a hook listener responds with an HTTP status code of < 200 or >=300 (or does not respond), the hook is considered to have failed and will be automatically reissued.

5.1.1 Timeouts

Hooks are set with a connect timeout of 10 seconds and a read timeout of 30 seconds. That means that if your hook listener doesn't respond within the timeout period, it will be considered a failure (with result "Unable to connect" or "Read timed out" in your hook activity) and it will be retried. If you expect your listener to take more than 10+30 seconds to respond during normal processing, you might consider issuing the response before your processing is complete. Or, do some background processing of lengthy jobs. Or, make your hook tolerant of the retries. Or, any other solution you'd like to come up with.

5.2 Automatic Retries

Failed hooks are automatically retried on an exponential backoff schedule. After 16 total attempts over approximately 18 hours, the hook will be marked as "fatal". Too many fatal hooks and the hook will be auto-disabled. You may manually reenable a hook but any events occurring between auto-disable and reenable cannot be rerun.

5.2.1 Idempotence

Due to the potential for retries as mentioned, it is highly recommended that any logic executed in your hook listener is idempotent. In short, you'll want to make your listener logic tolerant of any retry (unexpected or otherwise) so that you do not have any adverse affects of your logic running more than once.

5.3 Manual Retries and Canceling Retries

Cheddar includes a hook management console for you to manually rerun a hook or cancel automatic retries. The hook management console can be found here.

Any hook may be retried manually no matter its current state. You may also cancel or stop automatic retries for an individual hook event or in bulk by marking a hook or hooks as "complete" or "fatal".

View Plans and Pricing   or   Get Started with Cheddar now →