zapier-platform-cli 12.2.1 → 14.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,17 +16,17 @@ Zapier is a platform for creating integrations and workflows. This CLI is your g
16
16
 
17
17
  You may find docs duplicate or outdated across the Zapier site. The most up-to-date contents are always available on GitHub:
18
18
 
19
- - [Latest CLI Docs](https://github.com/zapier/zapier-platform/blob/master/packages/cli/README.md)
20
- - [Latest CLI Reference](https://github.com/zapier/zapier-platform/blob/master/packages/cli/docs/cli.md)
21
- - [Latest Schema Docs](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md)
19
+ - [Latest CLI Docs](https://github.com/zapier/zapier-platform/blob/main/packages/cli/README.md)
20
+ - [Latest CLI Reference](https://github.com/zapier/zapier-platform/blob/main/packages/cli/docs/cli.md)
21
+ - [Latest Schema Docs](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md)
22
22
 
23
- Our code is updated frequently. To see a full list of changes, look no further than [the CHANGELOG](https://github.com/zapier/zapier-platform/blob/master/CHANGELOG.md).
23
+ Our code is updated frequently. To see a full list of changes, look no further than [the CHANGELOG](https://github.com/zapier/zapier-platform/blob/main/CHANGELOG.md).
24
24
 
25
- This doc describes the latest CLI version (**12.2.1**), as of this writing. If you're using an older version of the CLI, you may want to check out these historical releases:
25
+ This doc describes the latest CLI version (**14.0.0**), as of this writing. If you're using an older version of the CLI, you may want to check out these historical releases:
26
26
 
27
- - CLI Docs: [10.2.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@10.2.0/packages/cli/README.md), [9.6.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@9.6.0/packages/cli/README.md), [8.4.2](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@8.4.2/packages/cli/README.md)
28
- - CLI Reference: [10.2.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@10.2.0/packages/cli/docs/cli.md), [9.6.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@9.6.0/packages/cli/docs/cli.md), [8.4.2](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@8.4.2/packages/cli/docs/cli.md)
29
- - Schema Docs: [10.2.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-schema@10.2.0/packages/schema/docs/build/schema.md), [9.6.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-schema@9.6.0/packages/schema/docs/build/schema.md), [8.4.2](https://github.com/zapier/zapier-platform/blob/zapier-platform-schema@8.4.2/packages/schema/docs/build/schema.md)
27
+ - CLI Docs: [11.3.3](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@11.3.3/packages/cli/README.md), [10.2.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@10.2.0/packages/cli/README.md), [9.7.3](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@9.7.3/packages/cli/README.md)
28
+ - CLI Reference: [11.3.3](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@11.3.3/packages/cli/docs/cli.md), [10.2.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@10.2.0/packages/cli/docs/cli.md), [9.7.3](https://github.com/zapier/zapier-platform/blob/zapier-platform-cli@9.7.3/packages/cli/docs/cli.md)
29
+ - Schema Docs: [11.3.3](https://github.com/zapier/zapier-platform/blob/zapier-platform-schema@11.3.3/packages/schema/docs/build/schema.md), [10.2.0](https://github.com/zapier/zapier-platform/blob/zapier-platform-schema@10.2.0/packages/schema/docs/build/schema.md), [9.7.3](https://github.com/zapier/zapier-platform/blob/zapier-platform-schema@9.7.3/packages/schema/docs/build/schema.md)
30
30
 
31
31
  ## Table of Contents
32
32
 
@@ -55,11 +55,13 @@ This doc describes the latest CLI version (**12.2.1**), as of this writing. If y
55
55
  * [Session](#session)
56
56
  * [OAuth1](#oauth1)
57
57
  * [OAuth2](#oauth2)
58
+ * [OAuth2 with PKCE](#oauth2-with-pkce)
58
59
  * [Connection Label](#connection-label)
59
60
  - [Resources](#resources)
60
61
  * [Resource Definition](#resource-definition)
61
62
  - [Triggers/Searches/Creates](#triggerssearchescreates)
62
63
  * [Return Types](#return-types)
64
+ + [Returning Line Items (Array of Objects)](#returning-line-items-array-of-objects)
63
65
  * [Fallback Sample](#fallback-sample)
64
66
  - [Input Fields](#input-fields)
65
67
  * [Custom/Dynamic Fields](#customdynamic-fields)
@@ -157,7 +159,7 @@ This doc describes the latest CLI version (**12.2.1**), as of this writing. If y
157
159
  > Note: this document uses "app" while modern Zapier nomenclature refers instead to "integrations". In both cases, the phrase refers to your code that connects your API with Zapier.
158
160
 
159
161
  A CLI App is an implementation of your app's API. You build a Node.js application
160
- that exports a single object ([JSON Schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#appschema)) and upload it to Zapier.
162
+ that exports a single object ([JSON Schema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#appschema)) and upload it to Zapier.
161
163
  Zapier introspects that definition to find out what your app is capable of and
162
164
  what options to present end users in the Zap Editor.
163
165
 
@@ -186,15 +188,15 @@ Zapier Platform CLI is designed to be used by development teams who collaborate
186
188
 
187
189
  ### Requirements
188
190
 
189
- All Zapier CLI apps are run using Node.js `v14`.
191
+ All Zapier CLI apps are run using Node.js `v16`.
190
192
 
191
- You can develop using any version of Node you'd like, but your eventual code must be compatible with `v14`. If you're using features not yet available in `v14`, you can transpile your code to a compatible format with [Babel](https://babeljs.io/) (or similar).
193
+ You can develop using any version of Node you'd like, but your eventual code must be compatible with `v16`. If you're using features not yet available in `v16`, you can transpile your code to a compatible format with [Babel](https://babeljs.io/) (or similar).
192
194
 
193
- To ensure stability for our users, we strongly encourage you run tests on `v14` sometime before your code reaches users. This can be done multiple ways.
195
+ To ensure stability for our users, we strongly encourage you run tests on `v16` sometime before your code reaches users. This can be done multiple ways.
194
196
 
195
- Firstly, by using a CI tool (like [Travis CI](https://travis-ci.org/) or [Circle CI](https://circleci.com/), which are free for open source projects). We provide a sample [.travis.yml](https://github.com/zapier/zapier-platform/blob/master/example-apps/trigger/.travis.yml) file in our template apps to get you started.
197
+ Firstly, by using a CI tool (like [Travis CI](https://travis-ci.org/) or [Circle CI](https://circleci.com/), which are free for open source projects). We provide a sample [.travis.yml](https://github.com/zapier/zapier-platform/blob/main/example-apps/trigger/.travis.yml) file in our template apps to get you started.
196
198
 
197
- Alternatively, you can change your local node version with tools such as [nvm](https://github.com/nvm-sh/nvm#installation-and-update). Then you can either swap to that version with `nvm use v14`, or do `nvm exec v14 zapier test` so you can run tests without having to switch versions while developing.
199
+ Alternatively, you can change your local node version with tools such as [nvm](https://github.com/nvm-sh/nvm#installation-and-update). Then you can either swap to that version with `nvm use v16`, or do `nvm exec v16 zapier test` so you can run tests without having to switch versions while developing.
198
200
 
199
201
 
200
202
  ### Quick Setup Guide
@@ -223,7 +225,7 @@ cd example-app
223
225
  npm install
224
226
  ```
225
227
 
226
- > Note: When you run `zapier init`, you'll be presented with a list of templates to start with. Pick the one that matches a feature you'll need (such as "dynamic-dropdown" for an integration with [dynamic dropdown fields](#dynamic-dropdowns)), or select "minimal" for an integration with only the essentials. [View more example apps here](https://github.com/zapier/zapier-platform/tree/master/example-apps).
228
+ > Note: When you run `zapier init`, you'll be presented with a list of templates to start with. Pick the one that matches a feature you'll need (such as "dynamic-dropdown" for an integration with [dynamic dropdown fields](#dynamic-dropdowns)), or select "minimal" for an integration with only the essentials. [View more example apps here](https://github.com/zapier/zapier-platform/tree/main/example-apps).
227
229
 
228
230
  You should now have a working local app. You can run several local commands to try it out.
229
231
 
@@ -452,7 +454,7 @@ When a user authenticates to your application through Zapier, a "connection" is
452
454
 
453
455
  Useful if your app requires two pieces of information to authenticate: `username` and `password`, 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).
454
456
 
455
- > To create a new integration with basic authentication, run `zapier init [your app name] --template basic-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/basic-auth).
457
+ > To create a new integration with basic authentication, run `zapier init [your app name] --template basic-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/main/example-apps/basic-auth).
456
458
 
457
459
  If your app uses Basic auth with an encoded API key rather than a username and password, like `Authorization: Basic APIKEYHERE:x`, consider the [Custom](#custom) authentication method instead.
458
460
 
@@ -469,7 +471,7 @@ const authentication = {
469
471
 
470
472
  const App = {
471
473
  // ...
472
- authentication: authentication,
474
+ authentication,
473
475
  // ...
474
476
  };
475
477
 
@@ -481,7 +483,7 @@ const App = {
481
483
 
482
484
  The setup and user experience of Digest Auth is identical to Basic Auth. Users provide Zapier their username and password, and Zapier handles all the nonce and quality of protection details automatically.
483
485
 
484
- > To create a new integration with digest authentication, run `zapier init [your app name] --template digest-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/digest-auth).
486
+ > To create a new integration with digest authentication, run `zapier init [your app name] --template digest-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/main/example-apps/digest-auth).
485
487
 
486
488
  > Limitation: Currently, MD5-sess and SHA are not implemented. Only the MD5 algorithm is supported. In addition, server nonces are not reused. That means for every `z.request` call, Zapier will send an additional request beforehand to get the server nonce.
487
489
 
@@ -504,7 +506,7 @@ const authentication = {
504
506
 
505
507
  const App = {
506
508
  // ...
507
- authentication: authentication,
509
+ authentication,
508
510
  // ...
509
511
  };
510
512
 
@@ -514,15 +516,14 @@ const App = {
514
516
 
515
517
  Custom auth is most commonly used for apps that authenticate with API keys, although it also provides flexibility for any unusual authentication setup. You'll likely provide some custom `beforeRequest` middleware or a `requestTemplate` (see [Making HTTP Requests](#making-http-requests)) to pass in data returned from the authentication process, most commonly by adding/computing needed headers.
516
518
 
517
- > To create a new integration with custom authentication, run `zapier init [your app name] --template custom-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/custom-auth).
519
+ > To create a new integration with custom authentication, run `zapier init [your app name] --template custom-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/main/example-apps/custom-auth).
518
520
 
519
521
  ```js
520
522
  const authentication = {
521
523
  type: 'custom',
522
524
  // "test" could also be a function
523
525
  test: {
524
- url:
525
- 'https://{{bundle.authData.subdomain}}.example.com/api/accounts/me.json',
526
+ url: 'https://{{bundle.authData.subdomain}}.example.com/api/accounts/me.json',
526
527
  },
527
528
  fields: [
528
529
  {
@@ -551,7 +552,7 @@ const addApiKeyToHeader = (request, z, bundle) => {
551
552
 
552
553
  const App = {
553
554
  // ...
554
- authentication: authentication,
555
+ authentication,
555
556
  beforeRequest: [addApiKeyToHeader],
556
557
  // ...
557
558
  };
@@ -562,7 +563,7 @@ const App = {
562
563
 
563
564
  Session auth gives you the ability to exchange some user-provided data for some authentication data; for example, username and password for a session key. It can be used to implement almost any authentication method that uses that pattern - for example, alternative OAuth flows.
564
565
 
565
- > To create a new integration with session authentication, run `zapier init [your app name] --template session-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/session-auth).
566
+ > To create a new integration with session authentication, run `zapier init [your app name] --template session-auth`. You can also review an example of that code [here](https://github.com/zapier/zapier-platform/tree/main/example-apps/session-auth).
566
567
 
567
568
  ```js
568
569
  const getSessionKey = async (z, bundle) => {
@@ -623,7 +624,7 @@ const includeSessionKeyHeader = (request, z, bundle) => {
623
624
 
624
625
  const App = {
625
626
  // ...
626
- authentication: authentication,
627
+ authentication,
627
628
  beforeRequest: [includeSessionKeyHeader],
628
629
  // ...
629
630
  };
@@ -638,7 +639,7 @@ For Session auth, the function that fetches the additional authentication data n
638
639
 
639
640
  Zapier's OAuth1 implementation matches [Twitter](https://developer.twitter.com/en/docs/tutorials/authenticating-with-twitter-api-for-enterprise/authentication-method-overview#oauth1.0a) and [Trello](https://developer.atlassian.com/cloud/trello/guides/rest-api/authorization/#using-basic-oauth) implementations of the 3-legged OAuth flow.
640
641
 
641
- > To create a new integration with OAuth1, run `zapier init [your app name] --template oauth1-trello`. You can also check out [oauth1-trello](https://github.com/zapier/zapier-platform/tree/master/example-apps/oauth1-trello), [oauth1-tumblr](https://github.com/zapier/zapier-platform/tree/master/example-apps/oauth1-tumblr), and [oauth1-twitter](https://github.com/zapier/zapier-platform/tree/master/example-apps/oauth1-twitter) for working example apps with OAuth1.
642
+ > To create a new integration with OAuth1, run `zapier init [your app name] --template oauth1-trello`. You can also check out [oauth1-trello](https://github.com/zapier/zapier-platform/tree/main/example-apps/oauth1-trello), [oauth1-tumblr](https://github.com/zapier/zapier-platform/tree/main/example-apps/oauth1-tumblr), and [oauth1-twitter](https://github.com/zapier/zapier-platform/tree/main/example-apps/oauth1-twitter) for working example apps with OAuth1.
642
643
 
643
644
  The flow works like this:
644
645
 
@@ -741,7 +742,7 @@ const includeAccessToken = (req, z, bundle) => {
741
742
 
742
743
  const App = {
743
744
  // ...
744
- authentication: authentication,
745
+ authentication,
745
746
  beforeRequest: [includeAccessToken],
746
747
  // ...
747
748
  };
@@ -758,7 +759,7 @@ Also, `authentication.oauth1Config.getAccessToken` has access to the additional
758
759
 
759
760
  Zapier's OAuth2 implementation is based on the `authorization_code` flow, similar to [GitHub](https://developer.github.com/v3/oauth/) and [Facebook](https://developers.facebook.com/docs/authentication/server-side/).
760
761
 
761
- > To create a new integration with OAuth2, run `zapier init [your app name] --template oauth2`. You can also check out [our working example app](https://github.com/zapier/zapier-platform/tree/master/example-apps/oauth2).
762
+ > To create a new integration with OAuth2, run `zapier init [your app name] --template oauth2`. You can also check out [our working example app](https://github.com/zapier/zapier-platform/tree/main/example-apps/oauth2).
762
763
 
763
764
  If your app's OAuth2 flow uses a different grant type, such as `client_credentials`, try using [Session auth](#session) instead.
764
765
 
@@ -794,16 +795,14 @@ Your auth definition would look something like this:
794
795
  const authentication = {
795
796
  type: 'oauth2',
796
797
  test: {
797
- url:
798
- 'https://{{bundle.authData.subdomain}}.example.com/api/accounts/me.json',
798
+ url: 'https://{{bundle.authData.subdomain}}.example.com/api/accounts/me.json',
799
799
  },
800
800
  // you can provide additional fields for inclusion in authData
801
801
  oauth2Config: {
802
802
  // "authorizeUrl" could also be a function returning a string url
803
803
  authorizeUrl: {
804
804
  method: 'GET',
805
- url:
806
- 'https://{{bundle.inputData.subdomain}}.example.com/api/oauth2/authorize',
805
+ url: 'https://{{bundle.inputData.subdomain}}.example.com/api/oauth2/authorize',
807
806
  params: {
808
807
  client_id: '{{process.env.CLIENT_ID}}',
809
808
  state: '{{bundle.inputData.state}}',
@@ -815,8 +814,7 @@ const authentication = {
815
814
  // "getAccessToken" could also be a function returning an object
816
815
  getAccessToken: {
817
816
  method: 'POST',
818
- url:
819
- 'https://{{bundle.inputData.subdomain}}.example.com/api/v2/oauth2/token',
817
+ url: 'https://{{bundle.inputData.subdomain}}.example.com/api/v2/oauth2/token',
820
818
  body: {
821
819
  code: '{{bundle.inputData.code}}',
822
820
  client_id: '{{process.env.CLIENT_ID}}',
@@ -850,7 +848,7 @@ const addBearerHeader = (request, z, bundle) => {
850
848
 
851
849
  const App = {
852
850
  // ...
853
- authentication: authentication,
851
+ authentication,
854
852
  beforeRequest: [addBearerHeader],
855
853
  // ...
856
854
  };
@@ -865,6 +863,99 @@ Also, `authentication.oauth2Config.getAccessToken` has access to the additional
865
863
 
866
864
  If you define `fields` to collect additional details from the user, please note that `client_id` and `client_secret` are reserved keys and cannot be used as keys for input form fields.
867
865
 
866
+
867
+ ### OAuth2 with PKCE
868
+
869
+ *Added in v14.0.0.*
870
+
871
+ Zapier's OAuth2 implementation also supports [PKCE](https://oauth.net/2/pkce/). This implementation is an extension of the OAuth2 `authorization_code` flow described above.
872
+
873
+ To use PKCE in your OAuth2 flow, you'll need to set the following variables:
874
+ 1. `enablePkce: true`
875
+ 2. `getAccessToken.body` to include `code_verifier: "{{bundle.inputData.code_verifier}}"`
876
+
877
+ The OAuth2 PKCE flow uses the same flow as OAuth2 but adds a few extra parameters:
878
+
879
+ 1. Zapier computes a `code_verifier` and `code_challenge` internally and stores the `code_verifier` in the Zapier bundle.
880
+ 2. Zapier sends the user to the authorization URL defined by your app, passing along the computed `code_challenge`.
881
+ 3. Once authorized, your website sends the user to the `redirect_uri` Zapier provided.
882
+ 4. Zapier makes a call to your API to exchange the `code` and the computed `code_verifier` for an `access_token`.
883
+ 5. Zapier stores the `access_token` and uses it to make calls on behalf of the user.
884
+
885
+ Your auth definition would look something like this:
886
+
887
+ ```js
888
+ const authentication = {
889
+ type: 'oauth2',
890
+ test: {
891
+ url: 'https://{{bundle.authData.subdomain}}.example.com/api/accounts/me.json',
892
+ },
893
+ // you can provide additional fields for inclusion in authData
894
+ oauth2Config: {
895
+ // "authorizeUrl" could also be a function returning a string url
896
+ authorizeUrl: {
897
+ method: 'GET',
898
+ url: 'https://{{bundle.inputData.subdomain}}.example.com/api/oauth2/authorize',
899
+ params: {
900
+ client_id: '{{process.env.CLIENT_ID}}',
901
+ state: '{{bundle.inputData.state}}',
902
+ redirect_uri: '{{bundle.inputData.redirect_uri}}',
903
+ response_type: 'code',
904
+ },
905
+ },
906
+ // Zapier expects a response providing {access_token: 'abcd'}
907
+ // "getAccessToken" could also be a function returning an object
908
+ getAccessToken: {
909
+ method: 'POST',
910
+ url: 'https://{{bundle.inputData.subdomain}}.example.com/api/v2/oauth2/token',
911
+ body: {
912
+ code: '{{bundle.inputData.code}}',
913
+ client_id: '{{process.env.CLIENT_ID}}',
914
+ client_secret: '{{process.env.CLIENT_SECRET}}',
915
+ redirect_uri: '{{bundle.inputData.redirect_uri}}',
916
+ grant_type: 'authorization_code',
917
+ code_verifier: '{{bundle.inputData.code_verifier}}', // Added for PKCE
918
+ },
919
+ headers: {
920
+ 'Content-Type': 'application/x-www-form-urlencoded',
921
+ },
922
+ },
923
+ scope: 'read,write',
924
+ enablePkce: true, // Added for PKCE
925
+ },
926
+ // If you need any fields upfront, put them here
927
+ fields: [
928
+ { key: 'subdomain', type: 'string', required: true, default: 'app' },
929
+ // For OAuth2 we store `access_token` and `refresh_token` automatically
930
+ // in `bundle.authData` for future use. If you need to save/use something
931
+ // that the user shouldn't need to type/choose, add a "computed" field, like:
932
+ // {key: 'user_id': type: 'string', required: false, computed: true}
933
+ // And remember to return it in oauth2Config.getAccessToken/refreshAccessToken
934
+ ],
935
+ };
936
+
937
+ const addBearerHeader = (request, z, bundle) => {
938
+ if (bundle.authData && bundle.authData.access_token) {
939
+ request.headers.Authorization = `Bearer ${bundle.authData.access_token}`;
940
+ }
941
+ return request;
942
+ };
943
+
944
+ const App = {
945
+ // ...
946
+ authentication,
947
+ beforeRequest: [addBearerHeader],
948
+ // ...
949
+ };
950
+
951
+ module.exports = App;
952
+
953
+ ```
954
+
955
+ The computed `code_verifier` uses this standard: [RFC 7636 Code Verifier](https://www.rfc-editor.org/rfc/rfc7636#section-4.1)
956
+
957
+ The computed `code_challenge` uses this standard: [RFC 7636 Code Challenge](https://www.rfc-editor.org/rfc/rfc7636#section-4.2)
958
+
868
959
  ### Connection Label
869
960
 
870
961
  When a user connects to your app via Zapier and a connection is created to hold the related data in `bundle.authData`, the connection is automatically labeled with the app name. You also have the option of setting a connection label (`connectionLabel`), which can be extremely helpful to identify information like which user is connected or what instance of your app they are connected to. That way, users don't get confused if they have multiple connections to your app.
@@ -915,10 +1006,10 @@ This will generate the resource file and add the necessary statements to the `in
915
1006
  A resource has a few basic properties. The first is the `key`, which allows Zapier to identify the resource on our backend.
916
1007
  The second is the `noun`, the user-friendly name of the resource that is presented to users throughout the Zapier UI.
917
1008
 
918
- > Check out [this working example app](https://github.com/zapier/zapier-platform/tree/master/example-apps/resource) to see resources in action.
1009
+ > Check out [this working example app](https://github.com/zapier/zapier-platform/tree/main/example-apps/resource) to see resources in action.
919
1010
 
920
1011
  After those, there is a set of optional properties that tell Zapier what methods can be performed on the resource.
921
- The complete list of available methods can be found in the [Resource Schema Docs](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#resourceschema).
1012
+ The complete list of available methods can be found in the [Resource Schema Docs](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#resourceschema).
922
1013
  For now, let's focus on two:
923
1014
 
924
1015
  * `list` - Tells Zapier how to fetch a set of this resource. This becomes a Trigger in the Zapier Editor.
@@ -945,7 +1036,7 @@ const Recipe = {
945
1036
 
946
1037
  ```
947
1038
 
948
- The method is made up of two properties, a `display` and an `operation`. The `display` property ([schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#basicdisplayschema)) holds the info needed to present the method as an available Trigger in the Zapier Editor. The `operation` ([schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#resourceschema)) provides the implementation to make the API call.
1039
+ The method is made up of two properties, a `display` and an `operation`. The `display` property ([schema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#basicdisplayschema)) holds the info needed to present the method as an available Trigger in the Zapier Editor. The `operation` ([schema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#resourceschema)) provides the implementation to make the API call.
949
1040
 
950
1041
  Adding a create method looks very similar.
951
1042
 
@@ -1017,24 +1108,60 @@ const App = {
1017
1108
 
1018
1109
  ```
1019
1110
 
1020
- You can find more details on the definition for each by looking at the [Trigger Schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#triggerschema),
1021
- [Search Schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#searchschema), and [Create Schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#createschema).
1111
+ You can find more details on the definition for each by looking at the [Trigger Schema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#triggerschema),
1112
+ [Search Schema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#searchschema), and [Create Schema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#createschema).
1022
1113
 
1023
- > To create a new integration with a premade trigger, search, or create, run `zapier init [your app name]` and select from the list that appears. You can also check out our working example apps [here](https://github.com/zapier/zapier-platform/tree/master/example-apps).
1114
+ > To create a new integration with a premade trigger, search, or create, run `zapier init [your app name]` and select from the list that appears. You can also check out our working example apps [here](https://github.com/zapier/zapier-platform/tree/main/example-apps).
1024
1115
 
1025
1116
  > To add a trigger, search, or create to an existing integration, run `zapier scaffold [trigger|search|create] [noun]` to create the necessary files to your project. For example, `zapier scaffold trigger post` will create a new trigger called "New Post".
1026
1117
  ### Return Types
1027
1118
 
1028
- Each of the 3 types of function expects a certain type of object. As of core v1.0.11, there are automated checks to let you know when you're trying to pass the wrong type back. For reference, each expects:
1119
+ Each of the 3 types of function should return a certain data type for use by the platform. There are automated checks to let you know when you're trying to pass the wrong type back. For reference, each expects:
1029
1120
 
1030
1121
  | Method | Return Type | Notes |
1031
1122
  |---------|-------------|----------------------------------------------------------------------------------------------------------------------|
1032
- | Trigger | Array | 0 or more objects; passed to the [deduper](https://zapier.com/developer/documentation/v2/deduplication/) if polling |
1123
+ | Trigger | Array | 0 or more objects; passed to the [deduper](https://platform.zapier.com/docs/dedupe/) if polling |
1033
1124
  | Search | Array | 0 or more objects. Only the first object will be returned, so if len > 1, put the best match first |
1034
- | Action | Object | Return values are evaluated by [`isPlainObject`](https://lodash.com/docs#isPlainObject) |
1125
+ | Create | Object | Return values are evaluated by [`isPlainObject`](https://lodash.com/docs#isPlainObject) |
1035
1126
 
1036
1127
  When a trigger function returns an empty array, the Zap will not trigger. For REST Hook triggers, this can be used to filter data if the available subscription options are not specific enough for the Zap's needs.
1037
1128
 
1129
+ #### Returning Line Items (Array of Objects)
1130
+
1131
+ In some cases, you may want to include multiple items in the data you return for Searches or Creates. To do that, return the set of items as an array of objects under a descriptive key. This may be as part of another object (like items in an invoice) or as multiple top-level items.
1132
+
1133
+ For example, a Create Order action returning an order with multiple items might look like this:
1134
+
1135
+ ```
1136
+ order = {
1137
+ name: 'Zap Zaplar',
1138
+ total_cost: 25.96,
1139
+ items: [
1140
+ { name: 'Zapier T-Shirt', unit_price: 11.99, quantity: 3, line_amount: 35.97, category: 'shirts' },
1141
+ { name: 'Orange Widget', unit_price: 7.99, quantity: 10, line_amount: 79.90, category: 'widgets' },
1142
+ { name:'Stuff', unit_price: 2.99, quantity: 7, line_amount: 20.93, category: 'stuff' },
1143
+ { name: 'Allbird Shoes', unit_price: 2.99, quantity: 7, line_amount: 20.93, category: 'shoes' },
1144
+ ],
1145
+ zip: 01002
1146
+ }
1147
+ ```
1148
+
1149
+ While a Find Users search could return multiple items under an object key within an array, like this:
1150
+
1151
+ ```
1152
+ result = [{
1153
+ users: [
1154
+ { name: 'Zap Zaplar', age: 12, city: 'Columbia', region: 'Missouri' },
1155
+ { name: 'Orange Crush', age: 28, city: 'West Ocean City', region: 'Maryland' },
1156
+ { name: 'Lego Brick', age: 91, city: 'Billund', region: 'Denmark' },
1157
+ ],
1158
+ }];
1159
+ ```
1160
+
1161
+ A standard search would return just the inner array of users, and only the first user would be provided as a final result. Returning line items instead means that the "first result" return is the object containing all the user details within it.
1162
+
1163
+ Using the standard approach is recommended, because not all Zapier integrations support line items directly, so users may need to take additional actions to reformat this data for use in their Zaps. More detail on that at [Use line items in Zaps](https://zapier.com/help/create/basics/use-line-items-in-zaps). However, there are use cases where returning multiple results is helpful enough to outweigh that additional effort.
1164
+
1038
1165
  ### Fallback Sample
1039
1166
  In cases where Zapier needs to show an example record to the user, but we are unable to get a live example from the API, Zapier will fallback to this hard-coded sample. This should reflect the data structure of the Trigger's perform method, and have dummy values that we can show to any user.
1040
1167
 
@@ -1099,7 +1226,7 @@ Notably, fields come in different types, which may look and act differently in t
1099
1226
  | `password` | Displays entered characters as hidden, accepts text input. Does not accept input from previous steps. |
1100
1227
  | `copy` | Does not allow users enter data. Shows the value of the Markdown-formatted Help Text for the field as a rich text note in the Zap editor. Good for important notices to users. |
1101
1228
 
1102
- You can find more details on the different field schema options at [our Field Schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#fieldschema).
1229
+ You can find more details on the different field schema options at [our Field Schema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#fieldschema).
1103
1230
 
1104
1231
  ### Custom/Dynamic Fields
1105
1232
 
@@ -1494,7 +1621,7 @@ You can see examples of computed fields in the [OAuth2](#oauth2) or [Session Aut
1494
1621
 
1495
1622
  ### Nested & Children (Line Item) Fields
1496
1623
 
1497
- When your action needs to accept an array of items, you can include an input field with the `children` attribute. The `children` attribute accepts a list of [fields](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#fieldschema) that can be input for each item in this array.
1624
+ When your action needs to accept an array of items, you can include an input field with the `children` attribute. The `children` attribute accepts a list of [fields](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#fieldschema) that can be input for each item in this array.
1498
1625
 
1499
1626
  ```js
1500
1627
  const App = {
@@ -1540,7 +1667,7 @@ Output Fields are optional, but can be used to:
1540
1667
  - Define friendly labels for the returned fields. By default, we will *humanize* for example `my_key` as *My Key*.
1541
1668
  - Make sure that custom fields that may not be found in every live sample and - since they're custom to the connected account - cannot be defined in the static sample, can still be mapped.
1542
1669
 
1543
- The [schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#fieldschema) for `outputFields` is shared with `inputFields` but only the `key` and `required` properties are relevant.
1670
+ The [schema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#fieldschema) for `outputFields` is shared with `inputFields` but only the `key` and `required` properties are relevant.
1544
1671
 
1545
1672
  Custom/Dynamic Output Fields are defined in the same way as [Custom/Dynamic Input Fields](#customdynamic-fields).
1546
1673
 
@@ -1896,7 +2023,7 @@ module.exports = {
1896
2023
  };
1897
2024
  ```
1898
2025
 
1899
- Read more in the [REST hook example](https://github.com/zapier/zapier-platform/blob/master/example-apps/rest-hooks/triggers/recipe.js).
2026
+ Read more in the [REST hook example](https://github.com/zapier/zapier-platform/blob/main/example-apps/rest-hooks/triggers/recipe.js).
1900
2027
 
1901
2028
  ### `bundle.subscribeData`
1902
2029
 
@@ -1904,7 +2031,7 @@ Read more in the [REST hook example](https://github.com/zapier/zapier-platform/b
1904
2031
 
1905
2032
  This is an object that contains the data you returned from the `performSubscribe` function. It should contain whatever information you need send a `DELETE` request to your server to stop sending webhooks to Zapier.
1906
2033
 
1907
- Read more in the [REST hook example](https://github.com/zapier/zapier-platform/blob/master/example-apps/rest-hooks/triggers/recipe.js).
2034
+ Read more in the [REST hook example](https://github.com/zapier/zapier-platform/blob/main/example-apps/rest-hooks/triggers/recipe.js).
1908
2035
 
1909
2036
  ## Environment
1910
2037
 
@@ -2212,7 +2339,7 @@ Here is the full request lifecycle when you call `z.request({...})`:
2212
2339
 
2213
2340
  The resulting response object is returned from `z.request()`.
2214
2341
 
2215
- > Example App: check out https://github.com/zapier/zapier-platform/tree/master/example-apps/middleware for a working example app using HTTP middleware.
2342
+ > Example App: check out https://github.com/zapier/zapier-platform/tree/main/example-apps/middleware for a working example app using HTTP middleware.
2216
2343
 
2217
2344
  #### Error Response Handling
2218
2345
 
@@ -2259,7 +2386,7 @@ This behavior has changed periodically across major versions, which changes how/
2259
2386
 
2260
2387
  ![](https://cdn.zappy.app/e835d9beca1b6489a065d51a381613f3.png)
2261
2388
 
2262
- Ensure you're handling errors correctly for your platform version. The latest released version is **12.2.1**.
2389
+ Ensure you're handling errors correctly for your platform version. The latest released version is **14.0.0**.
2263
2390
 
2264
2391
  ### HTTP Request Options
2265
2392
 
@@ -2402,7 +2529,7 @@ const App = {
2402
2529
  // don't forget to register hydrators here!
2403
2530
  // it can be imported from any module
2404
2531
  hydrators: {
2405
- getMovieDetails: getMovieDetails,
2532
+ getMovieDetails,
2406
2533
  },
2407
2534
 
2408
2535
  triggers: {
@@ -2544,7 +2671,7 @@ module.exports = App;
2544
2671
 
2545
2672
  ```
2546
2673
 
2547
- > To create a new integration for handling files, run `zapier init [your app name] --template files`. You can also check out our working example app [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/files).
2674
+ > To create a new integration for handling files, run `zapier init [your app name] --template files`. You can also check out our working example app [here](https://github.com/zapier/zapier-platform/tree/main/example-apps/files).
2548
2675
 
2549
2676
 
2550
2677
  ## Logging
@@ -2696,15 +2823,12 @@ Example: `throw new z.errors.RefreshAuthError();`
2696
2823
  ### Handling Throttled Requests
2697
2824
 
2698
2825
  Since v11.2.0, there are two types of errors that can cause Zapier to throttle an operation and retry at a later time.
2699
- This is useful if the API you're interfacing with is reports it is receiving too many requests, often indicated by
2826
+ This is useful if the API you're interfacing with reports it is receiving too many requests, often indicated by
2700
2827
  receiving a response status code of 429.
2701
2828
 
2702
2829
  If a response receives a status code of 429 and is not caught, Zapier will re-attempt the operation after a delay.
2703
- The delay can be customized by the server response containing a
2704
- [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header.
2705
-
2706
- Another way to request Zapier retry an operation is to throw a `ThrottledError`, which may also optionally specify a
2707
- delay in seconds:
2830
+ The delay can be customized by the server response containing a specific
2831
+ [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header in your error response or with a specified time delay in seconds using a `ThrottledError`:
2708
2832
 
2709
2833
  ```js
2710
2834
  const yourAfterResponse = (resp) => {
@@ -2714,6 +2838,9 @@ const yourAfterResponse = (resp) => {
2714
2838
  return resp;
2715
2839
  };
2716
2840
  ```
2841
+ Instead of a user’s Zap erroring and halting, the request will be repeatedly retried at the specified time.
2842
+
2843
+ For throttled requests that occur during processing of a webhook trigger's perform, before results are produced; there is a max retry delay of 300 seconds and a default delay of 60 seconds if none is specified. For webhook processing only, if a request during the retry attempt is also throttled, it will not be re-attempted again.
2717
2844
 
2718
2845
  ## Testing
2719
2846
 
@@ -2914,7 +3041,7 @@ This makes it straightforward to integrate into your testing interface. For exam
2914
3041
  ```yaml
2915
3042
  language: node_js
2916
3043
  node_js:
2917
- - "v14"
3044
+ - "v16"
2918
3045
  before_script: npm install -g zapier-platform-cli
2919
3046
  script: CLIENT_ID=1234 CLIENT_SECRET=abcd zapier test
2920
3047
  ```
@@ -3097,17 +3224,17 @@ zapier push
3097
3224
 
3098
3225
  There are a lot of details left out - check out the full example app for a working setup.
3099
3226
 
3100
- > To create a new integration with Babel, run `zapier init [your app name] --template babel`. You can also check out our working example app [here](https://github.com/zapier/zapier-platform/tree/master/example-apps/babel).
3227
+ > To create a new integration with Babel, run `zapier init [your app name] --template babel`. You can also check out our working example app [here](https://github.com/zapier/zapier-platform/tree/main/example-apps/babel).
3101
3228
 
3102
3229
  ## FAQs
3103
3230
 
3104
3231
  ### Why doesn't Zapier support newer versions of Node.js?
3105
3232
 
3106
- We run your code on AWS Lambda, which only supports a few [versions](https://docs.aws.amazon.com/lambda/latest/dg/programming-model.html) of Node (the latest of which is `v14`. As that updates, so too will we.
3233
+ We run your code on AWS Lambda, which only supports a few [versions](https://docs.aws.amazon.com/lambda/latest/dg/programming-model.html) of Node. Sometimes that doesn't include the latest version. Additionally, with thousands of apps running on the Zapier platform, we have to be sure upgrading to the latest Node version will not have a negative impact.
3107
3234
 
3108
3235
  ### How do I manually set the Node.js version to run my app with?
3109
3236
 
3110
- Update your `zapier-platform-core` dependency in `package.json`. Each major version ties to a specific version of Node.js. You can find the mapping [here](https://github.com/zapier/zapier-platform/blob/master/packages/cli/src/version-store.js). We only support the version(s) supported by [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/programming-model.html).
3237
+ Update your `zapier-platform-core` dependency in `package.json`. Each major version ties to a specific version of Node.js. You can find the mapping [here](https://github.com/zapier/zapier-platform/blob/main/packages/cli/src/version-store.js). We only support the version(s) supported by [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/programming-model.html).
3111
3238
 
3112
3239
  **IMPORTANT CAVEAT**: AWS periodically deprecates Node versions as they reach EOL. They announce this[on their blog](https://aws.amazon.com/blogs/developer/node-js-6-is-approaching-end-of-life-upgrade-your-aws-lambda-functions-to-the-node-js-10-lts/). Similar info and dates are available on [github](https://github.com/nodejs/Release). Well before this date, we'll have a version of `core` that targets the newer Node version.
3113
3240
 
@@ -3310,7 +3437,7 @@ const performWithoutAsync = (z, bundle) => {
3310
3437
  return z.request(
3311
3438
  'https://5ae7ad3547436a00143e104d.mockapi.io/api/recipes',
3312
3439
  {
3313
- params: { cursor: cursor }, // if cursor is null, it's ignored here
3440
+ params: { cursor }, // if cursor is null, it's ignored here
3314
3441
  }
3315
3442
  );
3316
3443
  })
@@ -3336,7 +3463,7 @@ const performWithAsync = async (z, bundle) => {
3336
3463
  {
3337
3464
  // if cursor is null, it's sent as an empty query
3338
3465
  // param and should be ignored by the server
3339
- params: { cursor: cursor },
3466
+ params: { cursor },
3340
3467
  }
3341
3468
  );
3342
3469
 
@@ -3350,7 +3477,7 @@ const performWithAsync = async (z, bundle) => {
3350
3477
 
3351
3478
  Cursors are stored per-zap and last about an hour. Per the above, make sure to only include the cursor if `bundle.meta.page !== 0`, so you don't accidentally reuse a cursor from a previous poll.
3352
3479
 
3353
- Lastly, you need to set `canPaginate` to `true` in your polling definition (per the [schema](https://github.com/zapier/zapier-platform/blob/master/packages/schema/docs/build/schema.md#basicpollingoperationschema)) for the `z.cursor` methods to work as expected.
3480
+ Lastly, you need to set `canPaginate` to `true` in your polling definition (per the [schema](https://github.com/zapier/zapier-platform/blob/main/packages/schema/docs/build/schema.md#basicpollingoperationschema)) for the `z.cursor` methods to work as expected.
3354
3481
 
3355
3482
  <a id="dedup"></a>
3356
3483
  ### How does deduplication work?
@@ -3384,9 +3511,9 @@ InvalidParameterValueException An error occurred (InvalidParameterValueException
3384
3511
 
3385
3512
  ... then you need to update your `zapier-platform-core` dependency to a non-deprecated version that uses a newer version of Node.js. Complete the following instructions as soon as possible:
3386
3513
 
3387
- 1. Edit `package.json` to depend on a later major version of `zapier-platform-core`. There's a list of all breaking changes (marked with a :exclamation:) in the [changelog](https://github.com/zapier/zapier-platform/blob/master/CHANGELOG.md).
3514
+ 1. Edit `package.json` to depend on a later major version of `zapier-platform-core`. There's a list of all breaking changes (marked with a :exclamation:) in the [changelog](https://github.com/zapier/zapier-platform/blob/main/CHANGELOG.md).
3388
3515
  2. Increment the `version` property in `package.json`
3389
- 3. Ensure you're using version `v14` (or greater) of node locally (`node -v`). Use [nvm](https://github.com/nvm-sh/nvm) to use a different one if need be.
3516
+ 3. Ensure you're using version `v16` (or greater) of node locally (`node -v`). Use [nvm](https://github.com/nvm-sh/nvm) to use a different one if need be.
3390
3517
  4. Run `rm -rf node_modules && npm i` to get a fresh copy of everything
3391
3518
  5. Run `zapier test` to ensure your tests still pass
3392
3519
  6. Run `zapier push`
@@ -3437,9 +3564,9 @@ Follow those instructions to enable completion for `zapier` commands and flags!
3437
3564
 
3438
3565
  The Zapier Platform consists of 3 npm packages that are released simultaneously.
3439
3566
 
3440
- - [`zapier-platform-cli`](https://github.com/zapier/zapier-platform/tree/master/packages/cli) is the code that powers the `zapier` command. You use it most commonly with the `test`, `scaffold`, and `push` commands. It's installed with `npm install -g zapier-platform-cli` and does not correspond to a particular app.
3441
- - [`zapier-platform-core`](https://github.com/zapier/zapier-platform/tree/master/packages/core) is what allows your app to interact with Zapier. It holds the `z` object and app tester code. Your app depends on a specific version of `zapier-platform-core` in the `package.json` file. It's installed via `npm install` along with the rest of your app's dependencies.
3442
- - [`zapier-platform-schema`](https://github.com/zapier/zapier-platform/tree/master/packages/schema) enforces app structure behind the scenes. It's a dependency of `core`, so it will be installed automatically.
3567
+ - [`zapier-platform-cli`](https://github.com/zapier/zapier-platform/tree/main/packages/cli) is the code that powers the `zapier` command. You use it most commonly with the `test`, `scaffold`, and `push` commands. It's installed with `npm install -g zapier-platform-cli` and does not correspond to a particular app.
3568
+ - [`zapier-platform-core`](https://github.com/zapier/zapier-platform/tree/main/packages/core) is what allows your app to interact with Zapier. It holds the `z` object and app tester code. Your app depends on a specific version of `zapier-platform-core` in the `package.json` file. It's installed via `npm install` along with the rest of your app's dependencies.
3569
+ - [`zapier-platform-schema`](https://github.com/zapier/zapier-platform/tree/main/packages/schema) enforces app structure behind the scenes. It's a dependency of `core`, so it will be installed automatically.
3443
3570
 
3444
3571
  To learn more about the structure of the code (especially if you're interested in contributing), check out the `ARCHITECTURE.md` file(s).
3445
3572
 
@@ -3447,12 +3574,12 @@ To learn more about the structure of the code (especially if you're interested i
3447
3574
 
3448
3575
  The Zapier platform and its tools are under active development. While you don't need to install every release, we release new versions because they are better than the last. We do our best to adhere to [Semantic Versioning](https://semver.org/) wherein we won't break your code unless there's a `major` release. Otherwise, we're just fixing bugs (`patch`) and adding features (`minor`).
3449
3576
 
3450
- Broadly speaking, all releases will continue to work indefinitely. While you never *have* to upgrade your app's `zapier-platform-core` dependency, we recommend keeping an eye on the [changelog](https://github.com/zapier/zapier-platform/blob/master/CHANGELOG.md) to see what new features and bug fixes are available.
3577
+ Broadly speaking, all releases will continue to work indefinitely. While you never *have* to upgrade your app's `zapier-platform-core` dependency, we recommend keeping an eye on the [changelog](https://github.com/zapier/zapier-platform/blob/main/CHANGELOG.md) to see what new features and bug fixes are available.
3451
3578
 
3452
3579
  For more info about which Node versions are supported, see [the faq](#how-do-i-manually-set-the-nodejs-version-to-run-my-app-with).
3453
3580
 
3454
3581
  <!-- TODO: if we decouple releases, change this -->
3455
- The most recently released version of `cli` and `core` is **12.2.1**. You can see the versions you're working with by running `zapier -v`.
3582
+ The most recently released version of `cli` and `core` is **14.0.0**. You can see the versions you're working with by running `zapier -v`.
3456
3583
 
3457
3584
  To update `cli`, run `npm install -g zapier-platform-cli`.
3458
3585
 
@@ -3468,4 +3595,4 @@ You can get help by either emailing `partners@zapier.com` or by [joining our dev
3468
3595
 
3469
3596
  ## Developing on the CLI
3470
3597
 
3471
- See [CONTRIBUTING.md](https://github.com/zapier/zapier-platform/blob/master/CONTRIBUTING.md).
3598
+ See [CONTRIBUTING.md](https://github.com/zapier/zapier-platform/blob/main/CONTRIBUTING.md).