Frequently Asked Questions

Does Zapier auto-save integrations?

No. Always remember to save your work when building integrations. Zapier asks you to save and continue in several spots while building integrations, so be sure to save at each point:

Save auth and API calls

When adding authentication and API calls for triggers or actions, there are Save & Continue buttons between each step. Click each one when you are finished adding details to your API call form or code mode editor.

Save triggers and actions

When adding a new trigger or action, there is a Save button after the Zap step details. Click that to save your new trigger or action step, before adding the input form and API configuration.

Save input fields

When adding a new field to an authentication, trigger, or action step’s input field, click Save after adding the field details.

How does Code Mode work?

Zapier visual builder code mode Each API call pane in Zapier visual builder includes a code mode toggle

The Zapier visual builder includes a form to add API endpoint URLs and choose the API call type, then automatically includes any authentication details and input form data with the API call. You can also set any custom options your API may need, including custom URL params, HTTP headers, and request body items. Zapier then parses JSON-encoded responses into individual output fields to use in subsequent Zap steps.

This is the best way to set up most API calls and options in Zapier integration authentication, triggers, and actions.

If your API calls need more customization, however, or your API response is in a non-JSON format, you will need to write custom JavaScript code to handle your API call and/or response parsing. The Zapier visual builder includes a Switch to Code Mode toggle on every API request, similar to the one pictured above, that switches that specific API call to code mode.

Remember: Code Mode is a toggle. Code Mode and Form Mode are saved separately; changes to one do not affect the other. The settings in the currently visible editor are the ones Zapier uses in your integration.

The first time you switch to code mode, Zapier copies everything entered in the API request form, including any custom options added, and converts them to JavaScript code. It then changes the UI to code mode, where you can add code for your API call.

In code mode, you can write JavaScript code, using Zapier’s default code as a base or writing custom code. Use the z.object for Zapier specific features, including z.console to write to the console log, z.JSON to parse JSON, z.errors to take action on errors, and more. Check Zapier’s CLI Z Object docs for details.

Additionally, use Zapier bundles to access auth data, data from user input forms, request data, and more. Learn more in our Zapier bundle docs.

Note: If you were familiar with our legacy Web Builder environment, we used to include several 3rd party libraries, like lodash, and made them available on the z object. Those libraries are not included in the new version of the UI tool. If you need access to additional modules you can easily move your project to the Zapier CLI and take advantage of npm to bring in any additional libraries you need.

Note that, in Code Mode you can import from Node’s standard library with z.require, for example, z.require('querystring') or z.require('crypto'). We strongly recommend you keep it simple when coding in the UI tool. The CLI is much better suited to building and testing complex code. And be sure you know what you’re doing - we can’t guarantee that everything you might use from the standard library will be supported in our platform’s runtime.

There is a time limit of 30 seconds for each trigger and action, so keep your custom code as light and quick as feasible. If code takes longer than 30 seconds to run, it will time out, and users’ Zaps will not be successful.

Do note that changes are not saved automatically. Once you have added the code you want, click Save & Continue to add the changes to your integration.

Zapier code mode switch to form mode Switch back to form mode to use the form mode settings instead of your custom code

Once you switch to code mode, Zapier uses your custom code for that API call, and does not use the data you previously entered in the form.

If you wish to switch back to the form mode, click the Switch to Form Mode button to see the form options as they were when you first switched to code mode. Zapier will save the code you entered, but will not convert it back to the form mode or use the custom code in your live integration.

You may switch back to code mode again—though this time, Zapier will show the last saved version of your code, and will not copy any changes from your API call form to the code.

Is my Zapier integration using the Form or Code Mode settings?

Zapier uses the currently visible option when running each part of your integration. If the form mode is visible for an API call in an integration’s authentication, trigger, or action settings, that Zapier integration is using the data from form mode. If the code mode is visible for an API call, Zapier is using the code instead to turn that part of the integration.

To check which mode and settings Zapier is using for each API call, open that part of your Zapier integration and visually check to see if the form or code mode is visible.

Why are options grayed out for my CLI-built integration?

Zapier CLI integration in visual builder

The Zapier Command Line Interface (CLI) is a separate SDK available to install on your local development machine to create Zapier integrations. It lets you work in code rather than a web based UI for more advanced integrations.

Integrations created in the CLI cannot be edited in the visual builder UI. You can’t add triggers or actions, edit code or configurations, for instance. Zapier’s platform site lists every integration you build, in the visual builder or CLI, but disables the core editing options for CLI-built integrations. These options will be grayed out in the UI.

You can manage the other details of your CLI integration from the UI, however, including:

  • Invite testers and collaborators
  • Monitor integration usage
  • Change environment variables
  • Submit your integration to be made publicly available
  • Promote a new integration version to public
  • Migrate users between versions

You can export a CLI version of your builder project to a CLI format that you can edit and maintain on your local development machine. You can then create and push new versions of your integration via Zapier CLI, and can manage the details from the visual builder UI or the CLI. Once you enable CLI, though, you will not be able to edit or add authentication, trigger, or action details in the visual builder UI.

If your app was originally built on our legacy platform, any custom code you wrote there will be accessible in a ‘scripting.js’ file in your exported CLI app.

Can I add files/attachments to a Trigger/Action using the Platform UI Visual Builder?

No. If you’d like to work with file attachments in your app, you’ll need to convert your app from the Visual Builder to the CLI platform instead.

What response type does Zapier expect?

With every API call, including authentication and auth testing calls, triggers, searches, and create actions, Zapier expects to receive response data from the API. If your API call does not return a response, Zapier will show a timeout error.

Zapier additionally expects different data for different API calls:

  • Object for Authentication, Auth testing, and Create Actions. Zapier expects to receive a single JSON formatted object with the correct details, including specific fields for Authentication calls depending on the auth scheme. Zapier will parse the individual fields and, with Create Actions, let users include their data in subsequent Zap steps.
  • Array for Triggers and Search Actions. Zapier expects to receive a JSON formatted array with the results in reverse chronological order. Even if the trigger or search only returns a single item, it should be formatted as an array. Zapier will then parse the results and return the most relevant result for searches, and return all new items from Triggers that pass Zapier’s deduper.

I got an “An array is expected” error. How do I fix that?

With you add a polling trigger or search action to a Zap, the Zapier platform expects to get a bare array of the new or found items, sorted in reverse chronological order. APIs will instead return a result object that contains the array of items the trigger needs.

For example, for a “New Channel” trigger with Slack’s API, we might start with a request:

Test it, though, and Zapier will show an error message like the one below:

Dig into the API response, and you’ll see that what was returned was an object that contains the array of items we need, not the array itself:

    "ok": true,
    "channels": [
            "id": "01234",
            "name": "general",
            "is_channel": true,
            "created": 1390943394,
            "is_archived": false,
            "is_general": true,
            "unlinked": 0,

What we need to return to Zapier is that array of channels. To do that we need to switch to “Code Mode” in our request. That lets us provide a JavaScript function to handle our request, where we can make needed changes to the structure or content of the result before we return data to the Zapier platform.

For this request, use return results.channels in line 18, instead of the default return results, to have Zapier return the array of results from channels.

Remember: “Code Mode” is a toggle; if you switch back to Form Mode your code will be ignored! Learn more.

Now, retest the request and it should run successfully. Note the response this time is a bare array:

Why does Zapier show censored fields in request and response data?

Example censored fields in Zapier

When testing Authentication, Triggers, or Actions in Zapier visual builder, you can see the raw data Zapier sends to your API call and receives from it in the Bundle and HTTP tabs of the testing pane. Some of those values may not be shown; instead, you’ll see a value like :censored:6:82a3be9927: as in the screenshot above.

Zapier automatically censors sensitive values at runtime, including all input fields marked as password and all authentication fields that will include sensitive, private data including username and password fields from Basic and Digest auth, API keys from API key auth, access and refresh tokens from Session and OAuth v2 authentication. These values are stored in the Auth bundle and used in API calls, but are replaced in Zapier’s logs with a censored value.

How do I clean up test authentication accounts?

Example account with multiple test accounts

While building your integration, testing authentication, and customizing your app’s connection label, you may quickly end up with a list of broken or old app authentications. You can clean those up and remove older accounts from your core Zapier account.

Remove authed accounts

Open your Zapier Connected Accounts page, and find your app’s name (you may need to use the search box or CMD+F (Mac) or Ctrl+F (PC)). Click the app name. Once on the app’s connections page, identify the connection to remove and click the three dots, then Delete, and confirm the deletion. Repeat for each subsequent testing account you added to clean up your authentication list.

Then refresh your integration page in the Visual Builder, and you’ll only see the authentications that were not deleted.

How do Sample Data and Output Fields work?

Adding Sample Data to Zapier integration Sample Data gives Zapier example data if users don’t test the trigger or action. Output Fields give your API data user-friendly names in subsequent Zap steps.

The last step in creating a new Trigger or Action for a Zapier integration is to Define your Output. Zapier asks both for Sample Data and Output Fields. Sample Data is especially important for Triggers, and useful with Actions as well. Output Fields are equally important for both triggers and actions, as the output data from both may be used in subsequent Zap steps.

Sample Data

Sample Data in a Zap Step

In the Zap Editor, Zapier will attempt to retrieve or create existing data to test Triggers and Actions. If users are in a hurry when building a Zap, or don’t have any data available, they can skip these test steps. Zapier will then show the sample data instead, so they can map fields correctly in subsequent Zap steps without seeing their account’s live data.

Make sure to provide JSON-formatted sample data using the same field names as your API. The sample response data should not include any personally identifiable data, have copy that is safe for work, and be easily recognizable as sample data.

When providing sample data, it’s also important that it only include fields that are present every time a Zap runs. When a field is provided in the sample, it can be mapped into a field in a later action.

If that field isn’t available when the user’s Zap runs, the action field will be empty, which can cause errors or unexpected results for users. For example, suppose your sample data looks like this:

  "id": 1,
  "first_name": "Jane",
  "last_name": "Suarez",
  "email_address": "",
  "job_title": "Executive Director"

A user might map the job_title information into a required field in another app, such as a CRM. Then, when the Zap runs, job_title is only included in the live result if it happens to be available, and the data the Zap receives looks like this:

  "id": 5,
  "first_name": "Jacob",
  "last_name": "Giotto",
  "email_address": ""

The user’s Zap will error unexpectedly when they try to add the person to their CRM because job_title is a required field in the CRM but there’s no data in it. Because this result is confusing, there are several integration checks that require sample and live data to match.

Output Fields

Output Fields add user-friendly labels to your API’s response data. Zapier uses a basic human-friendly transformation of field names by default, capitalizing words and adding spaces instead of underscores. You can customize this further with Output Fields.

For example, if you use GitHub’s API to watch for new issues, the API calls the issue name title. Users may expect that field to be called Issue or Issue Title, so you could define the Output Field as having the name Issue Title, rather than the default transformation of “Title”.

You can learn more about how Zapier uses sample data and output fields in triggers and actions.

How do I define Rest Hooks and use the embedded tester with them?

Rest Hooks are a great way to implement Zapier Triggers. They allow you to push new data as soon as it’s available in your product. You’ll also only connect when there is new data, and avoid polling altogether.

Rest Hooks are just webhooks plus an API endpoint for consumers to programatically subscribe and unsubscribe for updates. They are very powerful, but a bit more complex and involve a little more setup than polling triggers. By testing your rest hook configuration in the visual builder you can save time. You’ll shake out configuration issues before testing in the Zap editor, which will test the entire orchestrated transaction.

In the Zapier Platform we try to make setup easier by allowing you to test each individual request in isolation. In the test component of the visual builder, don’t create a real webhook listener. We mock out some data, and you’ll need to provide some of of your own mock data to evaluate whether your code is working the way you expect.

Let’s go through each of the requests required to create a working Rest Hook configuration, and how to test it in the visual builder.


This request is telling your API to send certain events related to this user’s account to Zapier. This is where the Zapier callback URL gets set.

Here’s an example using Gitlab’s API. Note that you’ll need to make sure the parameters here match what your API expects. In this case url is the field name that Gitlab expects to contain the webhook callback URL.

To skip ahead and test this in the visual builder, we hit Save API Request & Continue. Then go to Step 2 “Test Your API Request”. Because there are multiple requests that we will be testing here, start by selecting the Subscribe request we just configured.

Now to test if your subscribe end point is working as expected, enter test values for any user input required, and select Test Your Request. (Make sure you’ve successfully created a connected account)

Note that right now you may need to switch your Subscribe request to code mode in order for the embedded tester to function properly. We have a bug at the moment where we fail to swap bundle.targetUrl for a placeholder URL when using Form Mode.

Wait for the request to return, and review what your API returned. Note in particular the unique id of the subscription. We’ll need that value in a minute in order to test the unsubscribe request once we set that up. Also notice that what was sent to your API was a dummy webhook URL. At this point we haven’t spun up a real webhook listener. This test will just validate that we’re able to create a subscription in your API.

If your API checks that a webhook URL is live and valid during the subscription process this test step may not be all that valuable and you might proceed direcly to testing by creating a live Zap.

It’s a great idea to go and verify in your system to verify that the subscription was set up properly.


Unsubscribe is a request to your API to turn off sending webhook events for the Zap that calls it. This will be called whenever the Zap is turned off.

To configure and test the unsubscribe request we’ll repeat what we did setting up and testing Subscribe.

When we connect with your API to unsubscribe the webhook, we’ll need to tell it what the unique ID is of that subscription. When this happens in a Zap, the platform saves the id that was returned during the Subscribe request, and you can reference it in your unsubscribe request, on the bundle.subscribeData object.

To use the test component to validate that this request is configured properly, skip down again to step 2, and select the Unsubscribe request.

Note that right now you may need to switch your Subscribe request to code mode in order for the embedded tester to function properly. We have a bug at the moment where we fail to swap `` references for your test data.

In test configuration you’ll need to switch to ‘raw mode’. Raw mode lets you take more control over your test parameters than ‘pretty mode’.

Once in raw mode, find the subscribeData field. In this object, create an entry for the id of your web hook subscription. When used in a real Zap, this variable will be populated automatically based on the data that your Subscribe endpoint returns.

With that configured, click “Test Your Request”. You should now be able to confirm that the subscription is removed in your system, by reviewing the response message in the UI here, and by direct inspection in your system.

Perform List

A frequent question we get is “I’m building a rest hook - why do I need to define a polling endpoint?”. You define a “Perform List” to get actual data from your API to use as samples, to help the user set up Zaps with your trigger. Zap setup is the only place this request will be called, but it’s really important. Having the user’s data in the editor is critical for their success in getting a Zap configured and data mapped accurately. If you don’t define a PerformList, then the user needs to go into your app and do something to generate a new event while the Zap editor waits for data - it’s not an optimal experience.

This request works just like setting up and testing a polling trigger, and testing it with the embedded tester is straightforward.


Each time your API sends a web hook message to the Zap, the Zapier Platform will call the Javascript function you define in the Perform input. Use this if you need to manipulate the data in the payload prior to passing your result to subsequent Zap steps. Just return the appropriate object from bundle.cleanedRequest if you just want to pass along your webhooks payload without changing anything. You may need to put the response inside an array. We expect that the perform function returns a bare array of objects.

When using the embedded test tool, we aren’t testing with a real webhook. To test your perform function, you’ll need to grab some sample data that your webhook will send to your trigger. Go to the embedded test component, select the “Incoming Webhook Message” in the request selector and switch to “Raw Mode” in the embedded test tool.

Look for the cleanedRequest field. Find the body field inside the cleanedRequest field. This represents the body of the message your webhook service will send. Be sure to fill in any inputData that’s required as well. Paste your sample data there and click “Test Your Request”. This will pass run your perform function passing it your sample data. You’ll be able to see the result returned and any errors thrown. Add z.console.log() statements and you’ll see those in the “Console” tab.

Here’s an example of a configured test of our perform function. Our webhook, when actually running, will send an HTTP message with a JSON object called object_properties, so in order to test we simulate that here.

Once you’re happy with how all this is testing in the embedded tester, the next step is to go make a real Zap with your new Trigger and see how it works in the real world. Be sure to check the logs in the Monitoring component to get feedback from your Zap testing.

Need help? Tell us about your problem and we’ll connect you with the right resource or contact support.