REST Hooks#

Note: This documentation is for Zapier's legacy web builder. For new integrations, use Zapier Visual Builder and its new Trigger documentation.

Below is our simple standard to stop the Polling Madness™. This is a suggested pattern for you to implement. It was chosen because there are many examples of REST APIs providing resources around GETing, POSTing and DELETEing webhooks just like any other REST resource.

The big benefit to REST Hooks is consumers wouldn't need to poll for changes, but could instead wait for hooks to deliver the payload. Additionally, producers can provide real-time updates with fewer devoted resources (compared to polling).

The gist is: we POST a subscription to e.g. /api/hooks requesting to receive hooks at some target URL. Every time the event happens, ping us at the target URL with the payload.

After we're done, we can cleanup with a DELETE (.e.g. /api/hooks/:id).

Though we highly recommend this native pattern, you can override all the methods below with scripting. This means you can bend our pattern to match an existing pattern of your own.

Your Checklist#

  • enumerate the events you'd like to make available as triggers
  • create a subscribe REST endpoint for hooks. For example: POST /api/hooks
  • when each event happens, loop over and notify each active subscription (or batch events of same type). Note that each user may have multiple active subscriptions to the same event.
  • respect 410 responses on payload delivery and remove subscriptions
  • create a unsubscribe REST endpoint for hooks. For example: DELETE /api/hooks/:id
  • add a polling URL for your REST Hook trigger for the best user experience

You need to set the subscribe and unsubscribe REST endpoints under Manage Trigger Settings:

Manage Trigger Settings

Read on for a step by step through the endpoints involved...

Step 1: Subscribe (a call from Zapier to your app)#

POST <subscribe_endpoint> \
    -H Authenticated: Somehow \
    -H Content-Type: application/json \
    -d '{"target_url": "<unique_path>",
         "event": "user_created"}'

You may notice a duplicate property subscription_url. That's legacy terminology. You can safely ignore it and use target_url only.

This endpoint reuses whatever auth standard you have across the rest of your API (IE: Basic Auth, API Key, OAuth2, etc...). We'd send along a unique, auto-generated subscription URL and the event we'd like to subscribe to. These three items would be persisted on your backend (the authenticated user, target_url, and event).

The value for the subscribe_endpoint field can be specified within the "Manage Trigger Settings" option in your app's dashboard.

The value for the event field can be specified within the Trigger's setup:

If you prefer, you can modify this request to provide additional information (like any trigger fields) by defining a pre_subscribe scripting method. See the documentation and examples for more details.

On a successful subscribe, return a 201 status code. You should store data about the hook you just created via the post_subscribe scripting method (return an object like {"id": 1234}). You'll need this data later to unsubscribe, unless you use the subscription URL as the unique identifier, which is uncommon).

Generally, subscription URLs should be unique. Return a 409 status code if this criteria isn't met (IE: there is a uniqueness conflict).

Your service should permit a user to connect multiple webhook URLs to their account

We support validation of the receiver's intent to subscribe. When you send the X-Hook-Secret header, we'll reply to confirm we intended to subscribe.

Also, we'll provide X-Hook-Test: true in the header if the subscription hook is setup during the editor phase of a Zap -- this means the user is just testing the Zap. You might use this to send your own test hook immediately after subscription to help the user test the Zap (please add X-Hook-Test: true in your hook as well).

Step 2: Sending Hooks (a call from your app to Zapier)#

POST<unique_path> \
    -H Content-Type: application/json \
    -d <json payload>

This hook could provide any amount of data or payload in either JSON or XML (or form-encoded). See static webhooks on how we'll do our best to parse the response.

Usually Zapier expects an array of objects. If your API only sends a single object, wrap it in a single element array:

[ {"firstName": "Tom", "lastName": "Smith"} ]

On a successful hook, we'll return a 200 status code, content is irrelevant.

If Zapier responds with a 410 status code you should immediately remove the subscription to the failing hook (unsubscribe). Additionally, excessive failures (multiple 4xx or 5xx failures) can be handled at your discretion. It is the client's responsibility to resubscribe if needed after failures.

Step 3: Unsubscribe (a call from Zapier to your app)#

DELETE <unsubscribe_endpoint> \
    -H Authenticated: Somehow \
    -H Content-Type: application/json \
    -d <content built/omitted in pre_unsubscribe scripting method>

If you've properly stored identification data about the hook (like its unique ID) from the post_subscribe scripting method, you should use ourpre_unsubscribe scripting method to formulate the DELETE call. In that call you have access to your previously stored data under thebundle.subscribe_data variable.

Some example code is provided to make this as easy as possible. A heads up: you will need to use that code if you intend to do a DELETE call. You'll be able to access bundle.subscribe_data to build the URL in pre_unsubscribe. The default behavior is slightly different and listed below.

The value for the unsubscribe_endpoint field can be specified within the "Manage Trigger Settings" option in your app's dashboard.

However, the current default does not perform a DELETE. For example, if you omit the pre_unsubscribe function entirely, we will attempt a default unsubscribe call:

POST <unsubscribe_endpoint> \
    -H Content-Type: application/json \
    -d '{"target_url": "<unique_path>"}'

On a successful unsubscribe, return a 200 status code, content is irrelevant.

It is worth remembering that the subscription URL should effectively be unique (this could be enforced by your app as well) which also allows us to clean up unrecognized hooks (we also recommend not requiring authentication for such an endpoint).

Optional: Reverse Unsubscribe (a call from your app to Zapier)#

DELETE <target_url> \
    -H Content-Type: application/json

If you'd like to allow users to manage their subscriptions from inside your app (or maybe you are cleaning up after a user deletes their account or revokes credentials) you can issue a DELETE to the unique target URL which was generated when the subscription was created -- this will pause the Zap on Zapier's end.

Required to Go Public: Set a polling URL#

In the trigger setup, there is a field to define a polling URL. This URL will be used when users are setting up a Zap and must test it. Without this defined, the user must always go to your app, create a new data point, and have it send the hook to Zapier. This is not ideal, and in some cases may be particularly undesirable (if for example other Zaps are already set up on that hook, it would trigger them).

Setting up a polling URL fixes this. The polling URL is only used during this testing phase, not during the regular operation of the Zap. If you need to script special behavior, you can do so using the standard pre_poll and post_poll methods on the trigger key.

Please make sure the polling URL returns a list of resources ordered in reverse chronological order by created date, so the newest resources are returned first. Returning a list of resources will ensure users have multiple samples to work with. If no resources are available to be returned, please return an empty list/array.

Note: Please ensure that the data format that returns from the Polling URL is the same as what returns from the REST Hook, so users can correctly map fields.

↑ Was this documentation useful? Yes No