# Zapier > ## Documentation Index --- # Source: https://docs.zapier.com/platform/news/2025/4xx-errors-refreshAccessToken.md > ## Documentation Index > Fetch the complete documentation index at: https://docs.zapier.com/llms.txt > Use this file to discover all available pages before exploring further. # No more manual handling of 4xx errors in refreshAccessToken > We now automatically handle 4xx error responses when refreshing OAuth2 access tokens. *Effective: 2025-09-08* We made a change to how we handle error responses when refreshing OAuth2 access tokens. ## Old behavior When an app gives an error response (status code 4xx or 5xx) while refreshing the OAuth2 access token, Zapier keeps retrying the Zap step indefinitely or until it hits a certain limit, depending on the user's settings. ## New behavior When an app encounter a 4xx error response (except for the ones listed below) while refreshing the access token, Zapier will mark the connect as stale, and send an email telling the user to reconnect. Exceptions: The following 4xx errors often indicate a temporary issue so they still have the same behavior as before: * 408 (Request Timeout) * 409 (Conflict) * 423 (Locked) * 425 (Too Early) * 429 (Too Many Requests) This is how Zapier handles a stale connection: * If the stale connection is used by a trigger step, the trigger polling system will skip polling when the scheduled time comes. * If the stale connection is used by an action step, the Zap run will be put on hold until the user reconnects and replays the run. ## What does it mean to you? You don't need to handle 4xx error responses in `refreshAccessToken` anymore. For example, you might have been catching 4xx errors in `refreshAccessToken` by enabling `skipThrowForStatus` and throwing `ExpiredAuthError`: ```js theme={null} const refreshAccessToken = async (z, bundle) => { const response = await z.request({ url: "https://example.com/token/refresh", method: "POST", body: { refresh_token: bundle.authData.refresh_token, client_id: process.env.CLIENT_ID, client_secret: process.env.CLIENT_SECRET, grant_type: "refresh_token", }, headers: { "Content-Type": "application/x-www-form-urlencoded", }, skipThrowForStatus: true, }); if (response.status >= 400 && response.status < 500) { throw new z.errors.ExpiredAuthError( "Authentication issue. Please reconnect.", ); } return response.data; }; ``` This is no longer necessary. Now you can simplify your code as follows and let the platform handle it: ```js theme={null} const refreshAccessToken = async (z, bundle) => { const response = await z.request({ url: "https://example.com/token/refresh", method: "POST", body: { refresh_token: bundle.authData.refresh_token, client_id: process.env.CLIENT_ID, client_secret: process.env.CLIENT_SECRET, grant_type: "refresh_token", }, headers: { "Content-Type": "application/x-www-form-urlencoded", }, }); return response.data; }; ``` No need to upgrade zapier-platform-core; this change is implemented in the Zapier backend. --- # Source: https://docs.zapier.com/CLAUDE.md > ## Documentation Index > Fetch the complete documentation index at: https://docs.zapier.com/llms.txt > Use this file to discover all available pages before exploring further. # null # CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview This is Zapier's public API documentation site built with Mintlify. The docs are structured as a monorepo containing documentation for multiple Zapier products and solutions: * **Developer Platform** - Integration development tools and documentation * **Powered by Zapier** - Embeddable workflow APIs and components * **AI Actions** - AI-powered automation APIs * **MCP** - Model Context Protocol integration ## Development Commands ### Local Development ```bash theme={null} # Install dependencies pnpm i # Run locally pnpm run dev ``` ### Build and Quality Checks ```bash theme={null} # Format TypeScript files pnpm run format # Compile TypeScript pnpm run compile # Full build process (format + compile + scriptify) pnpm run build # Check for broken links pnpx mintlify broken-links ``` ### Pre-commit Hook The repository includes a TypeScript pre-commit hook (`pre-commit.ts`) that: * Downloads and processes OpenAPI schemas * Updates navigation configuration automatically * Validates links and routes * Ensures documentation consistency ## Project Structure ### Configuration Files * `docs.json` - Main Mintlify configuration with navigation structure * `package.json` - Node.js dependencies and scripts * `tsconfig.json` - TypeScript compilation settings * `ignore-endpoints` - Lists API endpoints to exclude from auto-generation ### Content Organization * `ai-actions/` - AI Actions API documentation and guides * `mcp/` - Model Context Protocol documentation * `platform/` - Developer Platform docs (CLI, UI, reference) * `powered-by-zapier/` - Embeddable workflows and APIs * `images/` - Static image assets * `snippets/` - Reusable content snippets ### Build Process The pre-commit hook automatically: 1. Fetches OpenAPI schemas from configured endpoints 2. Generates Mintlify documentation pages 3. Updates navigation configuration in `docs.json` 4. Validates all internal links and routes 5. Filters out ignored endpoints per `ignore-endpoints` file ## Key Architecture Notes * **Mintlify-based**: Uses Mintlify's documentation framework * **Auto-generated API docs**: OpenAPI schemas are automatically converted to MDX pages * **Multi-product structure**: Each major product has its own section with dedicated navigation * **Validation pipeline**: Automated checks ensure documentation consistency and link validity * **TypeScript tooling**: Build scripts and validation tools are written in TypeScript ## Working with Documentation * All content files use `.mdx` format * Navigation must be declared in `docs.json` to appear on the site * New pages require adding entries to the navigation configuration * API reference pages are auto-generated from OpenAPI schemas * Images should be placed in the `images/` directory * Use `snippets/` for content that needs to be reused across multiple pages ## Testing and Validation * Run `mintlify dev` for local development server * Use `pnpx mintlify broken-links` to check for broken internal links * The pre-commit hook validates route configurations automatically * Python script `check_redirects.py` can validate external links against localhost:3000 --- # Source: https://docs.zapier.com/powered-by-zapier/api-reference/common-types/action.md # Source: https://docs.zapier.com/platform/build/action.md > ## Documentation Index > Fetch the complete documentation index at: https://docs.zapier.com/llms.txt > Use this file to discover all available pages before exploring further. # Action > Every Zap starts with a single trigger that watches for new or updated data, starting the user's workflow. Action steps then make use of that data. Zapier actions create or update a single item in your app through API calls that include multiple details from user customized [input fields](/platform/build/add-fields). Zapier Action Visual Builder Zaps can have one or more actions. There are two types of actions to select. ## 1. Create actions Most Zapier integrations should at a minimum include create actions to let users add items to their app automatically. Common actions by app category [here](/platform/quickstart/must-have-triggers-and-actions) should be used for inspiration when building your app. *Create* actions in Zaps can create new items in an app or update existing items. The output returned should be an object containing individual fields that will be parsed for mapping into subsequent Zap steps. The [output returned](/platform/build/response-types) by a *create* should be an object containing individual fields about the item that was created such as IDs, details about the new item including a link if possible, and any other useful data about the record. Do not return just a `success` message. Unsucessful actions should return `4xx` errors. If your API returns a `2xx` error, add custom code to your API call to replace it with a correct error. Update actions should be separate from create actions. Actions may create multiple items if needed, using the same data, though you will likely need to customize the API call code to create multiple items at once. Only do this for linked items, such as if an app stores customers and customer addresses separately. If the multiple items that need to be created are top-level, complex items in your app, they should be separate actions within Zapier. You can then link the two with a drop-down menu in the action to select the paired item, add a search action for users to find the specific item they need, and then let them match the items with the [*Use a Custom Value* option](https://help.zapier.com/hc/en-us/articles/8496241696141) in Zapier. ## 2. Search actions *Search* actions find existing items in an app and can optionally be paired with *create* actions to [add a new item](/platform/build/search-or-create) if the search does not return a result. Search actions let users do more with the data they've already added to your app; such as avoiding adding duplicate items or look up info about an item, for example weather, conversion, and contact lookup, to use in a subsequent step. Most useful searches return one individual item that will likely be needed in another Zap step. The [output returned](/platform/build/response-types) by a *search* should be a JSON-formatted array sorted with the best match first. Only the first item will be returned. For no match found, a `200` with an empty array must be returned. If your API returns a `404` error for searches without results, add custom code to your API call to replace it with an empty array. ## 3. Delete actions Zapier recommends careful consideration of action steps that fully delete or remove data. To prevent data loss, action steps should only add or update data. If you are considering adding a delete action to your app, consider alternative actions for items such as deactivating, unsubscribing, or canceling, instead of deleting items completely. If you do add a delete action, make sure to include a `Copy` field to clarify to users that the action is irreversible once the API request is made. *** *Need help? [Tell us about your problem](https://developer.zapier.com/contact) and we'll connect you with the right resource or contact support.* --- # Source: https://docs.zapier.com/platform/manage/active-users.md > ## Documentation Index > Fetch the complete documentation index at: https://docs.zapier.com/llms.txt > Use this file to discover all available pages before exploring further. # Active users retention > At Zapier, churn means a user used your integration in their Zaps 29 - 56 days ago, but hasn't run a successful task in one of those Zaps in the past 28 days. This user is considered to have churned from the integration. Maybe they switched to using a competing integration or their workflow had a more periodic or seasonal cadence. But, it could also mean they got so frustrated with the experience of trying to get their Zap working and *keep* it working successfully - they turned it off, deleted it, and walked away. Active users are the percentage of users who haven't churned. ## Key Zapier insights Lowered active user retention rates don't necessarily mean poor integration health. Some apps lend themselves to use-cases with shorter lifespans than others. That said, spikes in churn rate not related to seasonal variations in usage could be indicators of a problem with something not functioning as expected. Active user retention is not a leading indicator. In fact, it's quite a lagging one that may only start indicating a problem up to 28 days after it has been an issue. That doesn't deem it useless, we just have to know how to make full use of it. ## Best practices Approaching active user retention with a long-term strategy can help maintain a consistently high level of retention: * [Embed](https://platform.zapier.com/embed/overview) the Zapier experience with copy-and-paste and customizable code within your platform to provide automation value directly to users. Embeds have proven to [reduce churn](https://platform.zapier.com/partner_success_stories/all) on Partners' platforms. Learn about embedding options in the [guide](https://learn.zapier.com/surface-your-zapier-integration-within-your-app). * [Share use cases](/platform/publish/partner-faq#tip-4-share-zapier-use-cases-in-your-onboarding) widely during your platform's onboarding process. Having multiple Zaps using your integration increases stickiness of users not only to the Zapier integration, but also to your platform. * Update the integration regularly with features as your platform evolves. [Invite stakeholders to your integration](/platform/manage/add-team) to give them admin or read-only access to insights, metrics, and feedback to prioritize and align improvements. *** *Need help? [Tell us about your problem](https://developer.zapier.com/contact) and we'll connect you with the right resource or contact support.* --- # Source: https://docs.zapier.com/platform/build/add-fields.md > ## Documentation Index > Fetch the complete documentation index at: https://docs.zapier.com/llms.txt > Use this file to discover all available pages before exploring further. # Add input fields to triggers and actions > When building in the Platform UI, you'll use the Input Designer to create the form users will input data into, to send to your app's API. The Input Designer works similarly to other form builder tools, building a form that lives inside the Platform UI. Add fields to your form for each bit of data your app needs from users. Use the same name for items as used in your app's UI. Configure each field's settings, then reorder them to match the logical order users would add or view data in your app. {" "} {" "} Actions require an input form, as they always need a way for users to send data to your app's API to find, update, or create a new object. An input form is optional for triggers. In this guide we will cover: * Add an input field to a trigger or action * Set field options * Reorder input fields * Remove input fields ## Add an input field to a trigger or action 1. Log into the [Platform UI](https://zapier.com/app/developer). 2. Select your **integration**. 3. In the *Build* section in the left sidebar, click on your **trigger** or **action**. 4. Click the **Input Designer** tab. 5. For triggers, click **Add User Input Field**. For actions, click **Add** and select **Input Field**. 6. In the Form editor, add in details about your input field: * **Key**: A unique identifier for the field, without spaces, ideally with the same key as your API, such as `first_name`. * **Label**: A user friendly name for the field, such as `First Name`. * **Help Text**: (optional) A 20 character or longer description that appears under the field label, with [Markdown](https://zapier.com/blog/beginner-ultimate-guide-markdown/) formatting. Do not include redundant help text in input fields that repeats the name of the field. Use field help text to tell users what to do, for example “Choose the directory to watch for new files”. Always use active voice. * **Type**: From the dropdown menu, select type of data you want user's to enter. Learn more in [field definitions and types](/platform/build/field-definitions): * String * Text * Integer * Number * Boolean * DateTime * Password * Dictionary * **Default Text**: (optional) Value to include in the field if the user leaves it blank; only include if this value would work for API requests made to every user's account. * **Options** (optional): * Select the **Required** checkbox to make it mandatory for users to add data into this input field. * Select **Allows Multiples** checkbox if you want users to add multiple enteries into the same input field. * Select **Alters Dynamic Fields** to have Zapier automatically recompute any dynamic fields any time this field is changed. * Select **Dropdown** 7. Once you've finished adding details for your input field, click **Save**. ## Setting field options ### Required An email app like MailChimp requires an email address to add a new email subscription, and a calendar app like Google Calendar requires an event title, date, and time to add new events. Check the *Required* option on those fields if your trigger or action step requires any data to make the API request. Zapier will show a red `(required)` label beside the field name in the Zap editor, and will not let users complete the Zap step without adding data to that field. {" "} {" "} Include a description on required fields to let users know exactly what type of data they should add to this field. Never mark fields as required if the integration could work without them. ### Allows multiples If users could add multiple entries in the same field, check the *Allows Multiples* option. {" "} {" "} That will add another entry row to allow the user to input another entry for that field. An [array containing a comma separated list of entries](/images/95938b473edfee13663161ee3c8e5ea4.webp) is sent in the API request. Never ask users to type in a comma separated list, rather use this functionality. ### Alters dynamic fields For each [dynamic field](/platform/build/dynamic-field) in your integration, Zapier runs code to decide whether to show a field or what to show in a field. Check the *Alters Dynamic Fields* option, to have Zapier automatically recompute any dynamic fields in your Zapier integration anytime this field is changed. Do not check the *Alters Dynamic Fields* option unless the field is needed for your integrations' dynamic fields. {" "} {" "} Only dropdowns support *Alters Dynamic Fields*. ### Dropdown #### Static Dropdown To offer users pre-set options to choose from in a field, set your field type as `String`, then check the *Dropdown* option. {" "} {" "} You'll see the default *Static* selected, or *Dynamic*. To add a Static menu of choices, type the options in a comma separated list, with quotes around each item and square brackets around the set, such as: `["one", "two","three"]` Enter the fields as used in your API, as Zapier will pass the exact value users select to your app. Zapier will capitalize each item in your dropdown menu in the Zap Editor, and will add spaces instead of any underscores, so an option like `first_name` would show in the menu as `First Name` to users. **Static Dropdown with Key Value Pairs** If your API requires different values for the field than the text you want to show to users inside the dropdown menu in Zapier, make a key value pair that includes the value to send to your API, the sample value to show users ([should be the same as the value](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#fieldchoicewithlabelschema)), and a user-friendly label. {" "} {" "} To do that, add each menu item inside an object (curly brackets); with the sample, value, and label comma separated. List the item first and the value second, both wrapped in quotes. Separate each menu item with commas, and wrap the whole set in an array (square brackets). For example, if your API expects a value of `1` or `2`, but `1` actually means `pork` and `2` actually means `fish` to a user, you could use the following code to add the dropdown menu pictured: ```JSON theme={null} [ { "sample": "1", "value": "1", "label": "Pork" }, { "sample": "2", "value": "2", "label": "Fish" } ] ``` Alternatively, you can also use the syntax of `value:label`, which shows to users as follows: {" "} {" "} {" "} {" "} #### Dynamic Dropdown If users need to select data from their account in your app — such as a project, folder, team member, or other user-specific detail with a corresponding ID — then you would use a dynamic dropdown. For dynamic dropdowns, Zapier first fetches data from your API and then displays it in a menu. Never make users type in an ID number, rather use this functionality or [add a search action](/platform/build/search) to find the ID number automatically. The best way to make a dynamic dropdown is to use a dedicated trigger to fetch the values for the menu. **1. Build a trigger to fetch dynamic dropdown data** Create a new trigger, with a key, name, and noun. This trigger is usually configured to not be seen by users but you may wish to include a description for your internal team's awareness. In the *Visibility in Editor* field, select `Hidden` to hide this trigger from your app's trigger list in Zapier. {" "} {" "} You can also use an existing, visible trigger to power a dynamic dropdown if applicable. Skip the *Input Designer* tab, as the dynamic dropdown cannot require any user input. Select the *API Configuration* tab, and add the API call where Zapier can fetch the data from your API. For standard Zapier triggers, you would use an API call that fetches new or updated items. For dynamic dropdowns, instead use an API call that pulls in a list of the items that the user can select from. {" "} {" "} API calls will usually require additional configuration to pull in data in the order that makes most sense in your menu. You may want to sort options in the order they were added or updated, or want to have the API fetch more items at once than the default. Set these parameters from the *Show Options* menu. {" "} {" "} If your API supports pagination, you can allow users to load additional data in the menu by checking the *Support Paging* box. The first API call might pull in 20 items; if the user requests additional items, Zapier would call the API again and request the second page for the next 20 items. *per\_page* and *limit* are common parameters to indicate how many items to pull (controlling the page size). Confirm which parameter to use from your API's documentation. Customize the pagination using [Code Mode](/platform/build/code-mode). Learn more about [how to use pagination in triggers](/platform/build/trigger#how-to-use-pagination). Zapier shows the data in the dropdown menu in the order your API sends it to Zapier. If your API sends the data in alphabetical order, or numerical order, it will show as such in your drop-down menu. If your API call supports sorting, include the sorting parameter in your API call that would return data in the order you want it to show in your drop-down. Define the fields from this hidden trigger that you need to use in the dynamic dropdown input field. To do so, test your trigger and identify the output fields needed, adding them to the *Output Fields* list at the end of your settings page. Include at least a field with the data that Zapier needs to send to your API in the action (for example `id`), along with a field that includes a user-friendly `name` for the data in that field. {" "} {" "} **2. Add an input field with dynamic fields** To use the data from the hidden trigger you've configured, add a new input field to the trigger/action you're working on, and set the label, key, and other details as normal. Check the *Dropdown* box and select the *Dynamic* toggle. Choose the hidden trigger you've configured for this menu in the *Dropdown Source* option. {" "} {" "} Select the field with the data your API needs for this action in the *Field Name* menu, and the field with a human-friendly name for the data in the *Field Label* menu. The [preview will indicate the presence of the field](/images/4780bb34f2f3d24062d2eb556ed1e3a9.webp), but you will need to use your trigger/action in a Zap to test the menu and pull in real data. When this trigger/action is selected in a Zap, the user will see a dropdown as Zapier polls your API for the data from that hidden trigger, parse the entries and extract the fields you specified, showing them in a user-friendly dropdown menu. The human-friendly name will be in larger, darker text, and the value to be sent to the API in smaller, lighter text. {" "} {" "} It is important to provide the API value (example `id`) for users to know what type of data the field expects. Users can also choose to [enter a custom value](/images/f72a12759a3b3b391025f6500f6c7904.webp) and map data from other Zap steps into this field. Being able to see what type of value to map is extremely helpful. **3. Add search to a dynamic field (optional)** Dynamic Dropdown menus can optionally include an additional *Add a Search Step* button beside the dropdown menu. This lets users dynamically select the correct item from a dynamic field based on input from previous Zap steps. {" "} {" "} You'll need to add a [Search Action](/platform/build/action#how-to-add-a-search-action) to find the items used in this dropdown menu. Then check the *Add a search to this field* option under the dynamic dropdown you've built, choose that action, and enter the ID of the field from that trigger that Zapier needs to pass with this API call (which should include the same data as the *Field Name* you selected before for the dynamic menu). {" "} {" "} When users click or add a search step in their Zap, Zapier will add a new search step before this action step.