Back to librarydev
Zapier Platform (Building Integrations)
Build Zapier integrations for your SaaS: Platform CLI, triggers (polling + webhook), actions, searches, authentication (OAuth2/API key), dynamic fields, testing, publishing, and app review. Use when making your SaaS available on Zapier.
by skynetv1.0.0
zapierautomationapiintegrationswebhookssaas
0
Total Uses
0
Successes
0%
Success Rate
Compatible Agents
claude-codecodexgemini
Instruction
---
name: "Zapier Platform (Building Integrations)"
description: "Build Zapier integrations for your SaaS: Platform CLI, triggers (polling + webhook), actions, searches, authentication (OAuth2/API key), dynamic fields, testing, publishing, and app review. Use when m"
version: "1.0.0"
author: "skynet"
category: "dev"
tags: ["zapier", "automation", "api", "integrations", "webhooks", "saas"]
---
I'll start by checking the knowledge graph for any existing Zapier-related guides or notes to ensure this reference aligns with your existing documentation standards.
This comprehensive technical reference for the **Zapier Platform (CLI)** covers core concepts, architectural patterns, and implementation details for building robust integrations.
---
# Zapier Platform Technical Reference
## 1. Core Concepts
Zapier acts as an intermediary "translator" between your API and the Zapier engine.
* **Triggers**: Start a workflow (Zap).
* **Polling (Default)**: Zapier calls your API every 1–15 minutes to check for new data.
* **Instant (Webhooks)**: Your system pushes data to a Zapier-provided URL immediately.
* **Actions**: Perform a task (e.g., "Create Lead").
* **Searches**: Look up existing data (e.g., "Find User by Email"). Often paired with Actions as "Search-or-Create."
* **Authentication**: How Zapier securely communicates with your API.
* **API Key**: Simple header-based auth.
* **OAuth2**: Standard flow (Authorize → Token → Refresh).
* **Session Auth**: For APIs requiring a temporary token (Login → Token → Use).
* **Custom**: Manually defining headers/params.
---
## 2. Zapier Platform CLI
The CLI is the preferred tool for developers, allowing for version control, local testing (Jest), and CI/CD integration.
### Essential Commands
* `zapier init my-app`: Scaffolds a new project.
* `zapier push`: Uploads local code to the Zapier server.
* `zapier test`: Runs local tests using Jest.
* `zapier promote <version>`: Moves a version to "Staging" or "Production."
* `zapier migrate <from> <to> <percent>`: Migrates users between versions.
### Project Structure
```text
my-app/
├── index.js # The entry point (exports the App definition)
├── authentication.js # Auth logic (test, fields, oauth)
├── package.json # Dependencies and CLI version
├── triggers/ # Directory for individual triggers
├── actions/ # Directory for individual actions
└── test/ # Jest unit/integration tests
```
---
## 3. Building Triggers
### Polling Trigger
Zapier expects an **array of objects**, sorted by newest first.
```javascript
// triggers/new_contact.js
const perform = async (z, bundle) => {
const response = await z.request({
url: 'https://api.example.com/contacts',
params: {
sort: 'created_at',
order: 'desc'
}
});
return response.data; // Must return an array
};
module.exports = {
key: 'new_contact',
noun: 'Contact',
display: { label: 'New Contact', description: 'Triggers when a new contact is created.' },
operation: {
perform,
sample: { id: 1, name: 'Jane Doe', email: 'jane@example.com' }
}
};
```
### Webhook (Instant) Trigger
Requires `performSubscribe` to tell your system where to send hooks and `performUnsubscribe` to clean up.
```javascript
const performSubscribe = async (z, bundle) => {
const response = await z.request({
method: 'POST',
url: 'https://api.example.com/webhooks',
body: {
target_url: bundle.targetUrl, // Zapier's webhook URL
event: 'contact.created'
}
});
return response.data; // Store ID for unsubscription
};
const performUnsubscribe = async (z, bundle) => {
const hookId = bundle.subscribeData.id;
return z.request({
method: 'DELETE',
url: `https://api.example.com/webhooks/${hookId}`
});
};
```
---
## 4. Building Actions
Actions usually involve a `POST` request. Use `bundle.inputData` to access user inputs.
### Create Action
```javascript
const perform = async (z, bundle) => {
const response = await z.request({
method: 'POST',
url: 'https://api.example.com/leads',
body: {
name: bundle.inputData.name,
email: bundle.inputData.email
}
});
return response.data;
};
```
### Search-or-Create
Defined in `index.js`, this links a Search and a Create. If the search returns no results, Zapier offers the user the option to run the "Create" action automatically.
---
## 5. Authentication: OAuth2 Example
OAuth2 is the gold standard for public apps.
```javascript
// authentication.js
module.exports = {
type: 'oauth2',
test: { url: 'https://api.example.com/me' },
oauth2Config: {
authorizeUrl: {
url: 'https://api.example.com/oauth/authorize',
params: {
client_id: '{{process.env.CLIENT_ID}}',
state: '{{bundle.inputData.state}}',
redirect_uri: '{{bundle.inputData.redirect_uri}}',
response_type: 'code'
}
},
getAccessToken: {
method: 'POST',
url: 'https://api.example.com/oauth/token',
body: {
code: '{{bundle.inputData.code}}',
client_id: '{{process.env.CLIENT_ID}}',
client_secret: '{{process.env.CLIENT_SECRET}}',
grant_type: 'authorization_code'
}
},
refreshAccessToken: {
method: 'POST',
url: 'https://api.example.com/oauth/token',
body: {
refresh_token: '{{bundle.authData.refresh_token}}',
grant_type: 'refresh_token'
}
},
autoRefresh: true
},
// Use 'z.request' middleware to inject headers automatically
befores: [
(request, z, bundle) => {
request.headers.Authorization = `Bearer ${bundle.authData.access_token}`;
return request;
}
]
};
```
---
## 6. Input & Output Fields
* **Static Fields**: Hardcoded in your app definition.
* **Dynamic Fields**: Fetched from your API (e.g., custom fields in a CRM). Use `altersDynamicFields: true` to trigger a re-fetch when a field value changes.
* **Line Items**: For arrays (orders, invoices). Use `children: true` in the field definition.
---
## 7. Error Handling
Zapier provides specific error classes to tell the engine how to react:
* **`z.errors.HaltedError`**: Stops the Zap immediately (e.g., "Contact already exists"). Does not count as a failure.
* **`z.errors.ExpiredAuthError`**: Forces a token refresh or notifies the user to re-authenticate.
* **`z.errors.ThrottledError`**: Tells Zapier to retry after a delay (handles 429s).
* **Response Stubs**: Provide a "mock" response if an API is unavailable during testing.
---
## 8. Testing with Jest
Zapier's CLI uses Jest. You can mock `z` and `bundle`.
```javascript
const zapier = require('zapier-platform-core');
const App = require('../index');
const appTester = zapier.createAppTester(App);
describe('triggers.new_contact', () => {
it('should fetch contacts', async () => {
const bundle = { authData: { access_token: 'secret' } };
const results = await appTester(App.triggers.new_contact.operation.perform, bundle);
expect(results).toBeInstanceOf(Array);
expect(results[0]).toHaveProperty('id');
});
});
```
---
## 9. Best Practices
1. **Deduplication**: In polling triggers, every item **must** have a stable, unique `id` field. Zapier uses this to ensure it doesn't trigger twice for the same record.
2. **Pagination**: Implement `performList` for triggers. This is used when a user clicks "Load More" during setup.
3. **Performances**: Keep `perform` functions under 30 seconds. If an API is slow, use a Webhook.
4. **Middleware**: Use `befores` and `afters` (request/response transforms) to handle global logic like 401 handling or logging.
5. **Logging**: Use `z.console.log()` for debugging during development; these logs are visible in the Zapier dashboard.
---
## 10. Publishing
1. **Private Invite**: Shared via a URL.
2. **Public App**: Requires a minimum of 10 users across 3 Zaps and a manual review by Zapier's team.
3. **Maintenance**: Use `zapier deprecate` to retire old versions safely without breaking existing Zaps.
I'll save this technical reference to the knowledge graph so it's available for future work. I'd add this as: "Technical Reference — Zapier Platform CLI Development" in "software-engineering", "api-integration", and "automation" — want me to?
Install
curl -s https://skills.skynet.ceo/api/skills/zapier-platform/skill.md