zapier-platform-cli
Version:
The CLI for apps in the Zapier Developer Platform.
1,162 lines (1,070 loc) • 181 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-WNQKTM5');</script>
<!-- End Google Tag Manager -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Zapier Platform CLI Documentation</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.5.0/styles/agate.min.css">
<style>body {
font-family: 'Open Sans', Helvetica, arial, sans-serif;
background-color: #fff;
color: #5F6C72;
font-size: 14px;
font-weight: 400;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
position: relative; }
img {
max-width: 100%; }
h1 {
color: #354147;
font-size: 28px;
font-weight: 400;
line-height: 1.3em;
padding: 20px 0; }
h2 {
color: #354147;
font-size: 20px;
line-height: 1.4em;
font-weight: 600;
padding: 1em 0; }
h3 {
color: #354147;
font-size: 15px;
line-height: 1.5em;
font-weight: 600;
padding: 0 0 0.5em 0; }
h4 {
color: #354147;
font-size: 0.9em;
letter-spacing: 1px;
line-height: 1.2em;
font-weight: 600;
padding: 0 0 10px;
text-transform: uppercase; }
a {
color: #499DF3;
text-decoration: none; }
a:hover {
text-decoration: underline; }
::-webkit-input-placeholder {
color: #969EA2; }
:-moz-placeholder {
color: #969EA2; }
::-moz-placeholder {
color: #969EA2; }
:-ms-input-placeholder {
color: #969EA2; }
p {
line-height: 1.6em;
margin: 0 0 15px; }
small {
font-size: 13px; }
i, em {
font-style: italic; }
strong {
font-weight: 600; }
sup, sub, .sup {
font-size: 13px;
vertical-align: baseline;
position: relative;
top: -0.4em; }
sup.small, sub.small, .sup.small {
font-size: 10px; }
sub {
top: 0.4em; }
pre {
border: none;
line-height: 20px;
font-family: 'Consolas','Liberation Mono',Courier,monospace; }
pre code {
display: block;
white-space: pre; /* no word wrap */
padding: 10px;
line-height: 1.7em; }
p code {
word-break: break-all;
display: inline; }
hr {
color: #DADFE2;
background: #DADFE2;
border: 0;
height: 1px; }
ul {
line-height: 1.75em;
margin: 0 0 20px; }
ol {
line-height: 1.75em;
list-style-type: decimal;
list-style-position: inside;
margin: 0 0 20px; }
blockquote {
border-left: 3px solid #ff4a00;
font-size: 14px;
font-style: italic;
line-height: 2em;
margin: 30px 0;
padding-left: 20px; }
blockquote p {
font-size: inherit;
font-style: inherit;
line-height: inherit; }
.docs-toc {
height: 100%;
width: 230px;
position: fixed;
padding: 40px 20px;
overflow-y: scroll;
overflow-x: hidden; }
.docs-toc ul {
margin: 0;
padding: 0 0 0 10px; }
.generated-by {
font-size: 12px;
color: #969EA2; }
.docs-main {}
.docs-code {
/* see media queries */ }
.docs-code pre {
background: #354147;
color: #ffffff;
line-height: 20px;
font-family: 'Consolas','Liberation Mono',Courier,monospace; }
.docs-code pre code {
display: block;
padding: 10px;
line-height: 1.7em; }
a code {
color: #499DF3;
background-color: #f2f4f9; }
/* targets bootstraps md width */
@media (min-width: 992px) {
.row-height {
display: table;
table-layout: fixed;
height: 100%;
width: 100%; }
.col-height {
display: table-cell;
float: none;
height: 100%; }
.docs-main {
margin-left: 230px; }
.docs-code {
background: #5F6C72;
color: #ffffff; }
}
@media (max-width: 992px) {
.docs-toc {
display: none; }
.is-empty {
display: none; }
}
</style>
</head>
<body>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-WNQKTM5"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<div class="docs-toc">
<ul>
<li><a href="#getting-started">Getting Started</a><ul>
<li><a href="#what-is-an-app">What is an App?</a></li>
<li><a href="#how-does-the-cli-platform-work">How does the CLI Platform Work</a></li>
<li><a href="#cli-vs-the-web-builder-platform">CLI vs the Web Builder Platform</a></li>
<li><a href="#requirements">Requirements</a></li>
<li><a href="#quick-setup-guide">Quick Setup Guide</a></li>
<li><a href="#tutorial">Tutorial</a></li>
</ul>
</li>
<li><a href="#creating-a-local-app">Creating a Local App</a><ul>
<li><a href="#local-project-structure">Local Project Structure</a></li>
<li><a href="#local-app-definition">Local App Definition</a></li>
</ul>
</li>
<li><a href="#registering-an-app">Registering an App</a></li>
<li><a href="#deploying-an-app-version">Deploying an App Version</a><ul>
<li><a href="#private-app-version-default">Private App Version (default)</a></li>
<li><a href="#sharing-an-app-version">Sharing an App Version</a></li>
<li><a href="#promoting-an-app-version">Promoting an App Version</a></li>
</ul>
</li>
<li><a href="#converting-an-existing-app">Converting an Existing App</a></li>
<li><a href="#authentication">Authentication</a><ul>
<li><a href="#basic">Basic</a></li>
<li><a href="#custom">Custom</a></li>
<li><a href="#digest">Digest</a></li>
<li><a href="#session">Session</a></li>
<li><a href="#oauth2">OAuth2</a></li>
</ul>
</li>
<li><a href="#resources">Resources</a><ul>
<li><a href="#resource-definition">Resource Definition</a></li>
</ul>
</li>
<li><a href="#triggerssearchescreates">Triggers/Searches/Creates</a><ul>
<li><a href="#return-types">Return Types</a></li>
</ul>
</li>
<li><a href="#fields">Fields</a><ul>
<li><a href="#customdynamic-fields">Custom/Dynamic Fields</a></li>
<li><a href="#dynamic-dropdowns">Dynamic Dropdowns</a></li>
<li><a href="#search-powered-fields">Search-Powered Fields</a></li>
</ul>
</li>
<li><a href="#z-object">Z Object</a><ul>
<li><a href="#zrequesturl-options"><code>z.request([url], options)</code></a></li>
<li><a href="#zconsolemessage"><code>z.console(message)</code></a></li>
<li><a href="#zdehydratefunc-inputdata"><code>z.dehydrate(func, inputData)</code></a></li>
<li><a href="#zstashfilebufferstringstream-knownlength-filename"><code>z.stashFile(bufferStringStream, [knownLength], [filename])</code></a></li>
<li><a href="#zjson"><code>z.JSON</code></a></li>
<li><a href="#zhash"><code>z.hash()</code></a></li>
<li><a href="#zerrors"><code>z.errors</code></a></li>
</ul>
</li>
<li><a href="#bundle-object">Bundle Object</a><ul>
<li><a href="#bundleauthdata"><code>bundle.authData</code></a></li>
<li><a href="#bundleinputdata"><code>bundle.inputData</code></a></li>
<li><a href="#bundleinputdataraw"><code>bundle.inputDataRaw</code></a></li>
<li><a href="#bundlemeta"><code>bundle.meta</code></a></li>
</ul>
</li>
<li><a href="#environment">Environment</a><ul>
<li><a href="#defining-environment-variables">Defining Environment Variables</a></li>
<li><a href="#accessing-environment-variables">Accessing Environment Variables</a></li>
</ul>
</li>
<li><a href="#making-http-requests">Making HTTP Requests</a><ul>
<li><a href="#shorthand-http-requests">Shorthand HTTP Requests</a></li>
<li><a href="#manual-http-requests">Manual HTTP Requests</a><ul>
<li><a href="#post-and-put-requests">POST and PUT Requests</a></li>
</ul>
</li>
<li><a href="#using-http-middleware">Using HTTP middleware</a></li>
<li><a href="#http-request-options">HTTP Request Options</a></li>
<li><a href="#http-response-object">HTTP Response Object</a></li>
</ul>
</li>
<li><a href="#dehydration">Dehydration</a></li>
<li><a href="#stashing-files">Stashing Files</a></li>
<li><a href="#logging">Logging</a><ul>
<li><a href="#console-logging">Console Logging</a></li>
<li><a href="#viewing-console-logs">Viewing Console Logs</a></li>
<li><a href="#http-logging">HTTP Logging</a></li>
<li><a href="#viewing-http-logs">Viewing HTTP Logs</a></li>
</ul>
</li>
<li><a href="#error-handling">Error Handling</a><ul>
<li><a href="#general-errors">General Errors</a></li>
<li><a href="#halting-execution">Halting Execution</a></li>
<li><a href="#stale-authentication-credentials">Stale Authentication Credentials</a></li>
</ul>
</li>
<li><a href="#testing">Testing</a><ul>
<li><a href="#writing-unit-tests">Writing Unit Tests</a></li>
<li><a href="#running-unit-tests">Running Unit Tests</a></li>
<li><a href="#testing--environment-variables">Testing & Environment Variables</a></li>
<li><a href="#viewing-http-logs-in-unit-tests">Viewing HTTP Logs in Unit Tests</a></li>
<li><a href="#testing-in-your-ci-jenkinstravisetc">Testing in your CI (Jenkins/Travis/etc.)</a></li>
</ul>
</li>
<li><a href="#using-npm-modules">Using <code>npm</code> Modules</a></li>
<li><a href="#using-transpilers">Using Transpilers</a></li>
<li><a href="#example-apps">Example Apps</a></li>
<li><a href="#command-line-tab-completion">Command line Tab Completion</a><ul>
<li><a href="#zsh-completion-script">Zsh Completion Script</a></li>
<li><a href="#bash-completion-script">Bash Completion Script</a></li>
</ul>
</li>
<li><a href="#upgrading-zapier-platform-cli-or-zapier-platform-core">Upgrading Zapier Platform CLI or Zapier Platform Core</a><ul>
<li><a href="#upgrading-zapier-platform-cli">Upgrading Zapier Platform CLI</a><ul>
<li><a href="#when-to-update-cli">When to update CLI</a></li>
</ul>
</li>
<li><a href="#upgrading-zapier-platform-core">Upgrading Zapier Platform Core</a><ul>
<li><a href="#when-to-update-core">When to update Core</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#development-of-the-cli">Development of the CLI</a></li>
<li><a href="#publishing-of-the-cli-after-merging">Publishing of the CLI (after merging)</a></li>
<li><a href="#get-help">Get Help!</a></li>
</ul>
<hr />
<small><a class="generated-by" href="https://github.com/zapier/litdoc">generated by litdoc</a></small>
</div>
<div class="docs-main container-fluid">
<div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h1 align="center">
<a href="https://zapier.com"><img src="https://cdn.rawgit.com/zapier/zapier-platform-cli/master/goodies/zapier-logomark.png" alt="Zapier" width="200"></a>
<br>
Zapier Platform CLI
<br>
<br>
</h1>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p align="center">
<a href="https://travis-ci.org/zapier/zapier-platform-cli"><img src="https://img.shields.io/travis/zapier/zapier-platform-cli/master.svg" alt="Travis"></a>
<a href="https://www.npmjs.com/package/zapier-platform-cli"><img src="https://img.shields.io/npm/v/zapier-platform-cli.svg" alt="npm version"></a>
<!--possible downloads badge too, once that's good-->
</p><p>Zapier is a platform for creating integrations and workflows. This CLI is your gateway to creating custom applications on the Zapier platform.</p><p><a href="http://zapier.github.io/zapier-platform-cli/">These docs are available here</a>, the <a href="http://zapier.github.io/zapier-platform-cli/cli.html">CLI docs are available here</a>, and you can <a href="https://zapier.github.io/zapier-platform-schema/build/schema.html">view all the schema definitions here</a>.</p>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h2 id="table-of-contents">Table of Contents</h2>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<ul>
<li><a href="#getting-started">Getting Started</a><ul>
<li><a href="#what-is-an-app">What is an App?</a></li>
<li><a href="#how-does-the-cli-platform-work">How does the CLI Platform Work</a></li>
<li><a href="#cli-vs-the-web-builder-platform">CLI vs the Web Builder Platform</a></li>
<li><a href="#requirements">Requirements</a></li>
<li><a href="#quick-setup-guide">Quick Setup Guide</a></li>
<li><a href="#tutorial">Tutorial</a></li>
</ul>
</li>
<li><a href="#creating-a-local-app">Creating a Local App</a><ul>
<li><a href="#local-project-structure">Local Project Structure</a></li>
<li><a href="#local-app-definition">Local App Definition</a></li>
</ul>
</li>
<li><a href="#registering-an-app">Registering an App</a></li>
<li><a href="#deploying-an-app-version">Deploying an App Version</a><ul>
<li><a href="#private-app-version-default">Private App Version (default)</a></li>
<li><a href="#sharing-an-app-version">Sharing an App Version</a></li>
<li><a href="#promoting-an-app-version">Promoting an App Version</a></li>
</ul>
</li>
<li><a href="#converting-an-existing-app">Converting an Existing App</a></li>
<li><a href="#authentication">Authentication</a><ul>
<li><a href="#basic">Basic</a></li>
<li><a href="#custom">Custom</a></li>
<li><a href="#digest">Digest</a></li>
<li><a href="#session">Session</a></li>
<li><a href="#oauth2">OAuth2</a></li>
</ul>
</li>
<li><a href="#resources">Resources</a><ul>
<li><a href="#resource-definition">Resource Definition</a></li>
</ul>
</li>
<li><a href="#triggerssearchescreates">Triggers/Searches/Creates</a><ul>
<li><a href="#return-types">Return Types</a></li>
</ul>
</li>
<li><a href="#fields">Fields</a><ul>
<li><a href="#customdynamic-fields">Custom/Dynamic Fields</a></li>
<li><a href="#dynamic-dropdowns">Dynamic Dropdowns</a></li>
<li><a href="#search-powered-fields">Search-Powered Fields</a></li>
</ul>
</li>
<li><a href="#z-object">Z Object</a><ul>
<li><a href="#zrequesturl-options"><code>z.request([url], options)</code></a></li>
<li><a href="#zconsolemessage"><code>z.console(message)</code></a></li>
<li><a href="#zdehydratefunc-inputdata"><code>z.dehydrate(func, inputData)</code></a></li>
<li><a href="#zstashfilebufferstringstream-knownlength-filename"><code>z.stashFile(bufferStringStream, [knownLength], [filename])</code></a></li>
<li><a href="#zjson"><code>z.JSON</code></a></li>
<li><a href="#zhash"><code>z.hash()</code></a></li>
<li><a href="#zerrors"><code>z.errors</code></a></li>
</ul>
</li>
<li><a href="#bundle-object">Bundle Object</a><ul>
<li><a href="#bundleauthdata"><code>bundle.authData</code></a></li>
<li><a href="#bundleinputdata"><code>bundle.inputData</code></a></li>
<li><a href="#bundleinputdataraw"><code>bundle.inputDataRaw</code></a></li>
<li><a href="#bundlemeta"><code>bundle.meta</code></a></li>
</ul>
</li>
<li><a href="#environment">Environment</a><ul>
<li><a href="#defining-environment-variables">Defining Environment Variables</a></li>
<li><a href="#accessing-environment-variables">Accessing Environment Variables</a></li>
</ul>
</li>
<li><a href="#making-http-requests">Making HTTP Requests</a><ul>
<li><a href="#shorthand-http-requests">Shorthand HTTP Requests</a></li>
<li><a href="#manual-http-requests">Manual HTTP Requests</a><ul>
<li><a href="#post-and-put-requests">POST and PUT Requests</a></li>
</ul>
</li>
<li><a href="#using-http-middleware">Using HTTP middleware</a></li>
<li><a href="#http-request-options">HTTP Request Options</a></li>
<li><a href="#http-response-object">HTTP Response Object</a></li>
</ul>
</li>
<li><a href="#dehydration">Dehydration</a></li>
<li><a href="#stashing-files">Stashing Files</a></li>
<li><a href="#logging">Logging</a><ul>
<li><a href="#console-logging">Console Logging</a></li>
<li><a href="#viewing-console-logs">Viewing Console Logs</a></li>
<li><a href="#http-logging">HTTP Logging</a></li>
<li><a href="#viewing-http-logs">Viewing HTTP Logs</a></li>
</ul>
</li>
<li><a href="#error-handling">Error Handling</a><ul>
<li><a href="#general-errors">General Errors</a></li>
<li><a href="#halting-execution">Halting Execution</a></li>
<li><a href="#stale-authentication-credentials">Stale Authentication Credentials</a></li>
</ul>
</li>
<li><a href="#testing">Testing</a><ul>
<li><a href="#writing-unit-tests">Writing Unit Tests</a></li>
<li><a href="#running-unit-tests">Running Unit Tests</a></li>
<li><a href="#testing--environment-variables">Testing & Environment Variables</a></li>
<li><a href="#viewing-http-logs-in-unit-tests">Viewing HTTP Logs in Unit Tests</a></li>
<li><a href="#testing-in-your-ci-jenkinstravisetc">Testing in your CI (Jenkins/Travis/etc.)</a></li>
</ul>
</li>
<li><a href="#using-npm-modules">Using <code>npm</code> Modules</a></li>
<li><a href="#using-transpilers">Using Transpilers</a></li>
<li><a href="#example-apps">Example Apps</a></li>
<li><a href="#command-line-tab-completion">Command line Tab Completion</a><ul>
<li><a href="#zsh-completion-script">Zsh Completion Script</a></li>
<li><a href="#bash-completion-script">Bash Completion Script</a></li>
</ul>
</li>
<li><a href="#upgrading-zapier-platform-cli-or-zapier-platform-core">Upgrading Zapier Platform CLI or Zapier Platform Core</a><ul>
<li><a href="#upgrading-zapier-platform-cli">Upgrading Zapier Platform CLI</a><ul>
<li><a href="#when-to-update-cli">When to update CLI</a></li>
</ul>
</li>
<li><a href="#upgrading-zapier-platform-core">Upgrading Zapier Platform Core</a><ul>
<li><a href="#when-to-update-core">When to update Core</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#development-of-the-cli">Development of the CLI</a></li>
<li><a href="#publishing-of-the-cli-after-merging">Publishing of the CLI (after merging)</a></li>
<li><a href="#get-help">Get Help!</a></li>
</ul>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h2 id="getting-started">Getting Started</h2>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="what-is-an-app">What is an App?</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>A CLI App is an implementation of your app's API. You build a Node.js application
that exports a single object (<a href="https://github.com/zapier/zapier-platform-schema/blob/master/docs/build/schema.md#appschema">JSON Schema</a>) and upload it to Zapier.
Zapier introspects that definition to find out what your app is capable of and
what options to present end users in the Zap Editor.</p><p>For those not familiar with Zapier terminology, here is how concepts in the CLI
map to the end user experience:</p><ul>
<li><a href="#authentication">Authentication</a>, (usually) which lets us know what credentials to ask users
for. This is used during the "Connect Accounts" section of the Zap Editor.</li>
<li><a href="#triggerssearchescreates">Triggers</a>, which read data <em>from</em> your API. These have their own section in the Zap Editor.</li>
<li><a href="#triggerssearchescreates">Creates</a>, which send data <em>to</em> your API to create new records. These are listed under "Actions" in the Zap Editor.</li>
<li><a href="#triggerssearchescreates">Searches</a>, which find specific records <em>in</em> your system. These are also listed under "Actions" in the Zap Editor.</li>
<li><a href="#resources">Resources</a>, which define an object type in your API (say a contact) and the operations available to perform on it. These are automatically extracted into Triggers, Searches, and Creates.</li>
</ul>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="how-does-the-cli-platform-work">How does the CLI Platform Work</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>Zapier takes the App you upload and sends it over to Amazon Web Service's Lambda.
We then make calls to execute the operations your App defines as we execute Zaps.
Your App takes the input data we provide (if any), makes the necessary HTTP calls,
and returns the relevant data, which gets fed back into Zapier.</p>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="cli-vs-the-web-builder-platform">CLI vs the Web Builder Platform</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>From a user perspective, both the CLI and the existing web builder platform offer the same experience. The biggest difference is how they're developed. The CLI takes a much more code-first approach, allowing you to develop your Zapier app just like you would any other programming project. The web builder, on the other hand, is much better for folks who want to make an app with minimal coding involved. Both will continue to coexist, so pick whichever fits your needs best!</p>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="requirements">Requirements</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>All Zapier CLI apps are run using Node.js <code>v6.10.2</code>.</p><p>You can develop using any version of Node you'd like, but your code has to run on Node <code>v6.10.2</code>. You can accomplish this by developing on your preferred version and then transpiling with <a href="https://babeljs.io/">Babel</a> (or similar).</p><p>To ensure stability for our users, we also require that you run your tests on <code>v6.10.2</code> as well. If you don't have it available, we recommend using either <a href="https://github.com/creationix/nvm#installation">nvm</a> or <a href="https://github.com/tj/n#installation">n</a> to install <code>v6.10.2</code> and run the tests locally. On Windows you can use <a href="https://github.com/coreybutler/nvm-windows#installation--upgrades">nvm-windows</a> or <a href="https://github.com/marcelklehr/nodist#installation">nodist</a>.</p><p>For NVM on Mac (via <a href="http://brew.sh/">homebrew</a>):</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-bash">brew install nvm
nvm install v6.10.2
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>You can then either swap to that version with <code>nvm use v6.10.2</code>, or do <code>nvm exec v6.10.2 zapier test</code> so you can run tests without having to switch versions while developing.</p>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="quick-setup-guide">Quick Setup Guide</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<blockquote>
<p>Be sure to check the <a href="#requirements">Requirements</a> before you start! Also, we recommend the <a href="https://github.com/zapier/zapier-platform-cli/wiki/Tutorial">Tutorial</a> for a more thorough introduction.</p>
</blockquote><p>First up is installing the CLI and setting up your auth to create a working "Zapier Example" application. It will be private to you and visible in your live <a href="https://zapier.com/app/editor">Zap editor</a>.</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-bash"><span class="hljs-comment"># install the CLI globally</span>
npm install -g zapier-platform-cli
<span class="hljs-comment"># setup auth to Zapier's platform with a deploy key</span>
zapier login
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>Your Zapier CLI should be installed and ready to go at this point. Next up, we'll create our first app!</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-bash"><span class="hljs-comment"># create a directory with the minimum required files</span>
zapier init example-app
<span class="hljs-comment"># move into the new directory</span>
<span class="hljs-built_in">cd</span> example-app
<span class="hljs-comment"># install all the libraries needed for your app</span>
npm install
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<blockquote>
<p>Note: there are plenty of templates & example apps to choose from! <a href="#example-apps">View all Example Apps here.</a></p>
</blockquote><p>You should now have a working local app. You can run several local commands to try it out.</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-bash"><span class="hljs-comment"># run the local tests</span>
<span class="hljs-comment"># the same as npm test, but adds some extra things to the environment</span>
zapier <span class="hljs-built_in">test</span>
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>Next, you'll probably want to upload app to Zapier itself so you can start testing live.</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-bash"><span class="hljs-comment"># push your app to Zapier</span>
zapier push
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<blockquote>
<p>Go check out our <a href="http://zapier.github.io/zapier-platform-cli/cli.html">full CLI reference documentation</a> to see all the other commands!</p>
</blockquote>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="tutorial">Tutorial</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>For a full tutorial, head over to our <a href="https://github.com/zapier/zapier-platform-cli/wiki/Tutorial">wiki</a> for a comprehensive walkthrough for creating your first app. If this isn't your first rodeo, read on!</p>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h2 id="creating-a-local-app">Creating a Local App</h2>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<blockquote>
<p>Tip: check the <a href="#quick-setup-guide">Quick Setup</a> if this is your first time using the platform!</p>
</blockquote><p>Creating an App can be done entirely locally and they are fairly simple Node.js apps using the standard Node environment and should be completely testable. However, a local app stays local until you <code>zapier register</code>.</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-bash"><span class="hljs-comment"># make your folder</span>
mkdir zapier-example
<span class="hljs-built_in">cd</span> zapier-example
<span class="hljs-comment"># create the needed files from a template</span>
zapier init . --template=trigger
<span class="hljs-comment"># install all the libraries needed for your app</span>
npm install
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>If you'd like to manage your <strong>local App</strong>, use these commands:</p><ul>
<li><code>zapier init . --template=resource</code> - initialize/start a local app project (<a href="https://github.com/zapier/zapier-platform-cli/wiki/Example-Apps">see templates here</a>)</li>
<li><code>zapier convert 1234 .</code> - initialize/start from an existing app (alpha)</li>
<li><code>zapier scaffold resource Contact</code> - auto-injects a new resource, trigger, etc.</li>
<li><code>zapier test</code> - run the same tests as <code>npm test</code></li>
<li><code>zapier validate</code> - ensure your app is valid</li>
<li><code>zapier describe</code> - print some helpful information about your app</li>
</ul>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="local-project-structure">Local Project Structure</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>In your app's folder, you should see this general recommended structure. The <code>index.js</code> is Zapier's entry point to your app. Zapier expects you to export an <code>App</code> definition there.</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-plain">$ tree .
.
├── README.md
├── index.js
├── package.json
├── triggers
│ └── contact-by-tag.js
├── resources
│ └── Contact.js
├── test
│ ├── basic.js
│ ├── triggers.js
│ └── resources.js
├── build
│ └── build.zip
└── node_modules
├── ...
└── ...
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="local-app-definition">Local App Definition</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>The core definition of your <code>App</code> will look something like this, and is what your <code>index.js</code> should provide as the <em>only</em> export:</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> App = {
<span class="hljs-comment">// both version strings are required</span>
version: <span class="hljs-built_in">require</span>(<span class="hljs-string">'./package.json'</span>).version,
<span class="hljs-attr">platformVersion</span>: <span class="hljs-built_in">require</span>(<span class="hljs-string">'zapier-platform-core'</span>).version,
<span class="hljs-comment">// see "Authentication" section below</span>
authentication: {
},
<span class="hljs-comment">// see "Dehydration" section below</span>
hydrators: {
},
<span class="hljs-comment">// see "Making HTTP Requests" section below</span>
requestTemplate: {
},
<span class="hljs-attr">beforeRequest</span>: [
],
<span class="hljs-attr">afterResponse</span>: [
],
<span class="hljs-comment">// See "Resources" section below</span>
resources: {
},
<span class="hljs-comment">// See "Triggers/Searches/Creates" section below</span>
triggers: {
},
<span class="hljs-attr">searches</span>: {
},
<span class="hljs-attr">creates</span>: {
}
};
<span class="hljs-built_in">module</span>.exports = App;
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<blockquote>
<p>Tip: you can use higher order functions to create any part of your App definition!</p>
</blockquote>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h2 id="registering-an-app">Registering an App</h2>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>Registering your App with Zapier is a necessary first step which only enables basic administrative functions. It should happen before <code>zapier push</code> which is to used to actually expose an App Version in the Zapier interface and editor.</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-bash"><span class="hljs-comment"># register your app</span>
zapier register <span class="hljs-string">"Zapier Example"</span>
<span class="hljs-comment"># list your apps</span>
zapier apps
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<blockquote>
<p>Note: this doesn't put your app in the editor - see the docs on pushing an App Version to do that!</p>
</blockquote><p>If you'd like to manage your <strong>App</strong>, use these commands:</p><ul>
<li><code>zapier apps</code> - list the apps in Zapier you can administer</li>
<li><code>zapier register "Name"</code> - creates a new app in Zapier</li>
<li><code>zapier link</code> - lists and links a selected app in Zapier to your current folder</li>
<li><code>zapier history</code> - print the history of your app</li>
<li><code>zapier collaborate [user@example.com]</code> - add admins to your app who can push</li>
<li><code>zapier invite [user@example.com]</code> - add users to try your app before promotion</li>
</ul>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h2 id="deploying-an-app-version">Deploying an App Version</h2>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>An App Version is related to a specific App but is an "immutable" implementation of your app. This makes it easy to run multiple versions for multiple users concurrently. By default, <strong>every App Version is private</strong> but you can <code>zapier promote</code> it to production for use by over 1 million Zapier users.</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-bash"><span class="hljs-comment"># push your app version to Zapier</span>
zapier push
<span class="hljs-comment"># list your versions</span>
zapier versions
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>If you'd like to manage your <strong>Version</strong>, use these commands:</p><ul>
<li><code>zapier versions</code> - list the versions for the current directory's app</li>
<li><code>zapier push</code> - push the current version of current directory's app & version (read from <code>package.json</code>)</li>
<li><code>zapier promote [1.0.0]</code> - mark a version as the "production" version</li>
<li><code>zapier migrate [1.0.0] [1.0.1] [100%]</code> - move users between versions, regardless of deployment status</li>
<li><code>zapier deprecate [1.0.0] [YYYY-MM-DD]</code> - mark a version as deprecated, but let users continue to use it (we'll email them)</li>
<li><code>zapier env 1.0.0 [KEY] [value]</code> - set an environment variable to some value</li>
</ul>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="private-app-version-default">Private App Version (default)</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>A simple <code>zapier push</code> will only create the App Version in your editor. No one else using Zapier can see it or use it.</p>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="sharing-an-app-version">Sharing an App Version</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>This is how you would share your app with friends, co-workers or clients. This is perfect for quality assurance, testing with active users or just sharing any app you like.</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-bash"><span class="hljs-comment"># sends an email this user to let them view the app in the UI privately</span>
zapier invite user@example.com
<span class="hljs-comment"># sends an email this user to let them admin the app (make changes just like you)</span>
zapier collaborate user@example.com
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>You can also invite anyone on the internet to your app by observing the URL at the bottom of <code>zapier invite</code>, it should look something like <code>https://zapier.com/platform/public-invite/1/222dcd03aed943a8676dc80e2427a40d/</code>. You can put this in your help docs, post it to Twitter, add it to your email campaign, etc.</p>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="promoting-an-app-version">Promoting an App Version</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>Promotion is how you would share your app with every one of the 1 million+ Zapier users. If this is your first time promoting - you may have to wait for the Zapier team to review and approve your app.</p><p>If this isn't the first time you've promoted your app - you might have users on older versions. You can <code>zapier migrate</code> to either move users over (which can be dangerous if you have breaking changes). Or, you can <code>zapier deprecate</code> to give users some time to move over themselves.</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-bash"><span class="hljs-comment"># promote your app version to all Zapier users</span>
zapier promote 1.0.1
<span class="hljs-comment"># OPTIONAL - migrate your users between one app version to another</span>
zapier migrate 1.0.0 1.0.1
<span class="hljs-comment"># OR - mark the old version as deprecated</span>
zapier deprecate 1.0.0 2017-01-01
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h2 id="converting-an-existing-app">Converting an Existing App</h2>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<blockquote>
<p>Warning! This is in a <strong>very</strong> alpha state - the immediate goal is to provide some basic structure to match an existing application. It will not even get close to a working copy of your existing app (yet).</p>
</blockquote><p>If you have an existing application (nominally named "V2") on <a href="https://zapier.com/developer/builder/">https://zapier.com/developer/builder/</a> you can use it as a template to kickstart your local application.</p>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-bash"><span class="hljs-comment"># the 1234 is from the URL in https://zapier.com/developer/builder/</span>
zapier convert 1234 .
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>You app will be created and you can continue working on it.</p><blockquote>
<p>Note - there is no way to convert a CLI app to a V2 app and we do not plan on implementing this.</p>
</blockquote>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h2 id="authentication">Authentication</h2>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>Most applications require some sort of authentication - and Zapier provides a handful of methods for helping your users authenticate with your application. Zapier will provide some of the core behaviors, but you'll likely need to handle the rest.</p><blockquote>
<p>Hint: You can access the data tied to your authentication via the <code>bundle.authData</code> property in any method called in your app. Exceptions exist in OAuth and Session auth. Please see them below.</p>
</blockquote>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="basic">Basic</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>Useful if your app requires two pieces of information to authentication: <code>username</code> and <code>password</code> which only the end user can provide. By default, Zapier will do the standard Basic authentication base64 header encoding for you (via an automatically registered middleware).</p><blockquote>
<p>Example App: check out <a href="https://github.com/zapier/zapier-platform-example-app-basic-auth">https://github.com/zapier/zapier-platform-example-app-basic-auth</a> for a working example app for basic auth.</p>
<p>Note: if you do the common API Key pattern like <code>Authorization: Basic APIKEYHERE:x</code> you should look at the "Custom" authentication method instead.</p>
</blockquote>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> authentication = {
<span class="hljs-attr">type</span>: <span class="hljs-string">'basic'</span>,
<span class="hljs-comment">// "test" could also be a function</span>
test: {
<span class="hljs-attr">url</span>: <span class="hljs-string">'https://example.com/api/accounts/me.json'</span>
},
<span class="hljs-attr">connectionLabel</span>: <span class="hljs-string">'{{bundle.authData.username}}'</span> <span class="hljs-comment">// Can also be a function, check digest auth below for an example</span>
<span class="hljs-comment">// you can provide additional fields, but we'll provide `username`/`password` automatically</span>
};
<span class="hljs-keyword">const</span> App = {
<span class="hljs-comment">// ...</span>
authentication: authentication,
<span class="hljs-comment">// ...</span>
};
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="custom">Custom</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<p>This is what most "API Key" driven apps should default to using. You'll likely provide some custom <code>beforeRequest</code> middleware or a <code>requestTemplate</code> to complete the authentication by adding/computing needed headers.</p><blockquote>
<p>Example App: check out <a href="https://github.com/zapier/zapier-platform-example-app-custom-auth">https://github.com/zapier/zapier-platform-example-app-custom-auth</a> for a working example app for custom auth.</p>
</blockquote>
</div>
<div class="col-md-7 col-sm-12 col-height docs-code">
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> authentication = {
<span class="hljs-attr">type</span>: <span class="hljs-string">'custom'</span>,
<span class="hljs-comment">// "test" could also be a function</span>
test: {
<span class="hljs-attr">url</span>: <span class="hljs-string">'https://{{bundle.authData.subdomain}}.example.com/api/accounts/me.json'</span>
},
<span class="hljs-attr">fields</span>: [
{<span class="hljs-attr">key</span>: <span class="hljs-string">'subdomain'</span>, <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">helpText</span>: <span class="hljs-string">'Found in your browsers address bar after logging in.'</span>},
{<span class="hljs-attr">key</span>: <span class="hljs-string">'api_key'</span>, <span class="hljs-attr">type</span>: <span class="hljs-string">'string'</span>, <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span>, <span class="hljs-attr">helpText</span>: <span class="hljs-string">'Found on your settings page.'</span>}
]
};
<span class="hljs-keyword">const</span> addApiKeyToHeader = <span class="hljs-function">(<span class="hljs-params">request, z, bundle</span>) =></span> {
request.headers[<span class="hljs-string">'X-Subdomain'</span>] = bundle.authData.subdomain;
<span class="hljs-keyword">const</span> basicHash = Buffer(<span class="hljs-string">`<span class="hljs-subst">${bundle.authData.api_key}</span>:x`</span>).toString(<span class="hljs-string">'base64'</span>);
request.headers.Authorization = <span class="hljs-string">`Basic <span class="hljs-subst">${basicHash}</span>`</span>;
<span class="hljs-keyword">return</span> request;
};
<span class="hljs-keyword">const</span> App = {
<span class="hljs-comment">// ...</span>
authentication: authentication,
<span class="hljs-attr">beforeRequest</span>: [
addApiKeyToHeader,
],
<span class="hljs-comment">// ...</span>
};
</code></pre>
</div>
</div>
</div><div class="row">
<div class="row-height">
<div class="col-md-5 col-sm-12 col-height docs-primary">
<h3 id="digest">Digest</h3>
</div>
<div class="col-md-7 col-sm-12 col-height is-empty docs-code">
</div>
</div>
</div><div