Integrating a CRM App on Zapier#


To learn the basics on how to build an integration with Zapier, you should first read through these two guides:

  1. Planning Guide - conceptualize what your integration will look like
  2. App Development Guide - best practices for how to implement your plan for your integration

This guide discusses some unique key considerations (UX and technical) when building a CRM integration with Zapier.


Trigger Requests and Copy#

Users typically expect the following types of triggers for CRM apps. These records may be named differently in your app - we recommend that you use the version of the name that appears in your UI so your customers know exactly what to expect:

  • New Contact (also: Person, Lead)
  • New Deal (also: Opportunity)
  • New Company (also: Organization)
  • New Tag
  • New Note
  • New Tag Added to Contact
  • New Contact in View (also: Filter)
  • New Contact in Stage (also: Group, Segment) - if your CRM has the ability to move a contact across a funnel, users often want to trigger off a contact newly appearing in a specific stage. For example, Pipedrive allows you to move a Deal across stages as Deals become more matured over time.

For other advice on copy we expect from all triggers, check out our Style Guide’s section on what language to use here.

Trigger behavior#

Basic expectations#

When records are newly created, they should trigger off a "New x" trigger. For example, when a new contact is created - not when an existing one is updated - it should trigger off a “New Contact” trigger.

REST Hooks#

We recommend you use REST Hooks if possible so they offer a real time flow of data once the record is completed. This is especially useful for the common use case where customers tag hundreds of contacts in bulk to trigger a workflow, which your API’s page size of results may not be able to sufficiently handle.

Updated information behavior#

Contacts typically change "relational data" - statuses, stages, and tags, or other records that demonstrate what kind of contact they are. Sometimes contacts will have some relational data applied, removed, and then re-applied as the contact changes over time. Users typically expect that when a user gets relational data that they’ve had previously, the Zap should trigger again.

If you are using webhooks, which we recommend for this purpose, ensure that when relational data is reapplied, you will still send us that record.

If you are using polling triggers, this may cause issues with how we perform deduplication, as we don’t consider that status, stage, or tag to be newly applied to that contact anymore. We strongly recommend adding extra scripting for deduplication so that it will trigger every time a tag is added, even if it has been added before. You can do this by adding a timestamp to the id field you’re using for deduplication so that the Zap triggers anew.

Setup options for your Triggers#

Some apps, such as Pipedrive and Salesforce, offer built-in filters or views in the app itself that users can set up. If your app has this ability we recommend displaying an optional dynamic dropdown of the user’s filters so they don’t have to re-create the filter again in the Zap, and instead are able to trigger off of new records in the views they’re already natively familiar with.


In the dynamic dropdown of a user’s existing groups or filters, consider ordering the dropdown list by the most recently added to make it easier for users to find the filter option they are mostly likely to choose.

Trigger response format#

Polling URL#

The polling URL should return the most recent record created, because it’s often more useful for a user to set up a Zap using a real entry they can recognize.

If there are no recent new records, you should return an empty array. This ensures that we’ll encourage the user to create a sample that is comprised of data types they’d ordinarily see, so they can re-test their trigger and finish mapping their Zap.

Obtaining Linked Information#

CRMs are unique because they can offer a wealth of records that are linked to other records. Getting the full context of linked information is useful. For example, if your trigger is "New Contact" and newly added contacts are linked to organizations, then users expect to get full organization data.

Linked information should be provided both as IDs so they’re easily mapped in your app’s action steps, as well as human-readable data like the name.

If the endpoint on a certain record type does not already return additional linked data beyond the ID or the name of the linked records, you can, implement z.request in scripting and use hydration/dehydration, as described here. This allows for a workflow where users trigger off New Contacts, but also get information from linked companies on the contacts, such as the organization’s contact information.


Custom fields#

If users typically use many custom fields to define their contacts or other record types, we recommend ensuring that these custom fields are returned in full - you may want to implement paging to ensure this.

We offer Custom Trigger Fields, which you can implement in scripting to ensure that the fields users see are not IDs, but rather human-readable labels that they can easily map in their Zaps.


Consider returning tags on new records as an array of strings or comma-delimited list in a single string, so users will be able to easily map this into another app.


Search Requests and Copy#

Users typically expect to have the following searches on a CRM app:

  • Find Contact (also: Person, Lead)
  • Find Deal (also: Opportunity)
  • Find Company (also: Organization)

For other advice on copy we expect from all searches, check out our Style Guide’s section on what language to use here.

Search Behavior#

This should find an already existing record, and return it in the same format that the trigger returns the same record in. This ensures that the user gets a consistent experience, and there aren’t any fields in a trigger that don’t appear in the corresponding search.

Setup Options#

Multiple search options#

Consider providing multiple search options by providing two fields: a search key as well as a search value. The search key should be a static dropdown of different fields users can search by - for a "Find Contact" type search, we suggest offering unique fields such as Email, ID, or Username. Users can then map the search value. Here's how Infusionsoft does it:

multiple search sample

Preventing Deduplication Problems#

If your CRM doesn’t allow multiple records that have the same value for a field (such as email), consider offering only a single search query for that field instead of providing multiple options. This prevents users from searching on a different field, trying to create a new record, and then being told that a record with that email already exists. Zoho CRM does this with their Find Contact search step - in this gif, the search is safely halted instead of errored when a record is not found.

single search sample

Parity Across Triggers#

Ensure that the field(s) you offer for searching are fields that are returned by the trigger steps. For example, a user might use a New Contact trigger, and then want to find out more information about the organization the contact is associated with by using a Find Organization search. If the New Contact trigger only provides the associated organization ID, it doesn’t make sense for the Find Organization search to only allow searching by the organization name.

Search Response Format#

Obtaining Linked Information#

We recommend using z.request in the post_poll method to ensure all relevant data is accessible. For example, if your trigger is "New Contact" and newly added contacts are linked to organizations, then users expect to get some organization as well.

Linked information should be provided both as IDs (so they’re easily mapped in your app’s action steps), as well as human-readable data like the name.

Error Handling#

If a record cannot be found, ensure that it returns a halted exception as opposed to an error.

Preventing duplicate records

Users often already have a CRM with plenty of contacts entered by the time they try out Zapier, and want to ensure they’re not entering duplicates. It’s very useful for your searches to be a combined "Search/Create" option that works by searching for a record, and then creating one if it’s not found.


Action Requests and Copy#

Users typically expect to have the following types of create actions for CRM apps. These should follow the "Create x" or “Add x” we recommend.

  • Create Contact (also: Person, Lead)
  • Create Deal (also: Opportunity)
  • Create Company (also: Organization)
  • Create Note

It’s also useful to include Update actions, as information on records in CRMs tend to change frequently. Any Update action you include should have a corresponding Search action to make it easier for users to update the correct record. For example, "Add Contact to Stage" needs to be paired with a Find Contact search.

  • Update Contact (also: Deal, Person, Opportunity, Lead)
  • Update Company (also: Organization)
  • Add Tag to Contact
  • Add Contact to Stage (also: Group, Segment)
  • Add Contact to Workflow (also: Sequence, Follow-up, Campaign)

For other advice on copy we expect from all apps, check out our Style Guide’s section on what language to use here.

Action behavior#

Multiple Linked Records#

Your CRM integration will be especially powerful if users can link other record types when creating a record. For example, in your app’s UI, users may be able to create a contact and link it to existing companies or stages.

It’s important to ensure that when a user creates a new contact through Zapier, this should only create new contacts, and should not also create other linked records at the same time. This reduces opportunity for error as well as record redundancy for the user.

Setup template for your Actions#

Custom Fields#

Custom fields should be displayed with a human-readable label instead of the internal ID. If the custom fields are radio selects, booleans, or can only accept certain values, ensure that these are displayed to the user using a static or dynamic dropdown.

Linked Records#

If your app’s UI allows for other record types to be linked, we recommend making that option available in the Zap template. Ensure that the linked record field is a dynamic dropdown populated with existing records. We strongly recommend that you add a search connector and a search step to make this the most streamlined experience for your users to set up.

An example of linking records is in Infusionsoft, where creating an invoice also allows you to associate a contact. The contact field in this case is also a dynamic dropdown, which we strongly recommend for displaying linked record fields to the user.



These are also known as sequences, follow-ups, and campaigns. If your app has the ability to have certain new records get automatically added to an in-app workflow, we recommend either ensuring that records created by Zapier will also get automatically added to workflows. You can also add a field during setup that asks the user if they’d like to add new records to in-app workflows, and provide "yes/no" options.

You can also have the option of letting the user define exactly which workflow they’d like to add the created record to, like Infusionsoft does in their Create/Update Contact Action.


Action response format#

Basic Expectations#

This should return at least the data that was created during the action step, to make it easier for users to map in subsequent steps and also see what was created. It should also include the ID of the created record as well as any linked records for faster mapping into subsequent steps.

For more information about what we like to see across all response content, check out our Style Guide section on it.


CRMs usually have both large numbers of records as well as custom fields. Be sure to implement pagination so it returns the full list of all records as well as order them most recent to least recent, so users are able to associate the records they want.

Implementation checklist#

  • If you are using webhooks, compare the data that’s returned in the polling fallback or static sample versus the data that’s returned by a live webhook.
  • Create a record with many custom fields and check to see what that looks like in a trigger/search.
  • Create a multi-step Zap (we recommend one trigger, search, and action step) to check the ease of linking one step to another.
  • If you have the option to link records in the action, check to see that these are linked correctly when creating records.

Next Steps#

  • See our Style Guide to learn more about other requirements for your integration such as branding.

  • Read our activation checklist to learn about making your app available globally.


Please let us know if you found this guide useful or have any feedback on how we can improve it.

↑ Was this documentation useful? Yes No