AI Actions AI alpha

Custom integration docs - Using the API

Dive into the nitty gritty details about how to use the API.


Basic example

Here's a basic example of how you can use the API:

curl -v \
    -d '{"instructions": "Add Bryan Helmig at Zapier to my test sheet, oh and he loves guitars!"}' \
    -H "Authorization: Bearer <ACCESS_TOKEN>" \
    -H "Content-Type: application/json" \
    'https://actions.zapier.com/api/v1/dynamic/exposed/<ACTION_ID>/execute/'

Mix in some fixed values:

curl -v \
    -d '{"instructions": "Send a short poem about automation to slack", "channel": "#fun-zapier"}' \
    -H "Authorization: Bearer <ACCESS_TOKEN>" \
    -H "Content-Type: application/json" \
    'https://actions.zapier.com/api/v1/dynamic/exposed/<ACTION_ID>/execute/'

The AI guessing flow

AI Actions is optimized for a chat-style usage paradigm where you want to offload as much work to a large language model (LLM), as possible. An action is run ("executed") via an API call with one single natural language parameter: instructions.

In the chat use case, these instructions are likely being generated by your own LLM. However, AI Actions works just as well even in more traditional software paradigm where instructions are perhaps hard-coded into your codebase or supplied by the user directly.

Whatever your use case is, AI Actions utilizes AI to attempt to "guess" field values required to run actions. This saves users tons of time in setting up their actions.

Let's walk through an example

Consider the case where you've built a chat product and your end user wants to expose a "Send Slack Message" action to your product. Their action setup might look like this.

The user only has to select their desired action ("Slack: Send Channel Message") and authorize their Slack account.

By default, all required fields are set to "Have AI guess a value for this field". We call these fields "hint parameters".

In this example there are two required fields: Channel and Message Text.

If a field uses "Have AI guess a value for this field", two things happen:

  1. When the action is run via the API, AI Actions will interpret passed instructions to fill in the values for Channel and Message Text. AI Actions is smart about fields like Channel where Slack's API requires a channel ID rather than a plain text channel name. AI Actions handles all such cases automatically.
  2. The field will be listed as an optional hint parameter in the OpenAPI spec, which allows you, the provider, to override any instructions guessing.

Overriding hint parameters

Sometimes language models hallucinate or guess wrong. And if this were a particuarly sensitive Slack message, the user may not want to leave the selection of Channel up to chance. AI Actions allows the user to use a specific, fixed value like this.

Now when the action is executed, Message Text will be automatically guessed, but Channel will be set to "#testing". This ability to override field hints significantly increases user trust and unlocks use cases where the user may have partial, but not full trust, in an AI guessing.

Hint parameters are always optional. When running actions via the API, you, the provider, can choose to supply none/any/all hint parameters. Any hint parameters provided are treated exactly like an action field set to "Use a specific value" as an override.

Custom fields

Zapier supports custom fields throughout the platform. The degenerate case is a spreadsheet, where every column is a custom field. This introduces complexity because spreadsheet columns are unknowable at action setup time if the user sets the action field that selects which spreadsheet to use as "Have AI guess a value for this field" (i.e. the spreadsheet will be chosen dynmically when the action is run).

AI Actions handles such custom fields using the same pattern as above with one distinction: they are not listed as hint parameters because they are literally unknowable until run time. Also, as you may expect, if the user picks a specific spreadsheet during action setup, custom fields act like regular fields and flow through normally.

In the typical chat product use case, you'll want to expose these hint parameters alongside the exposed action list to your own language model. Your LLM is likely to have broader context about the user vs the narrowly constrained instructions string passed to the API, and will therefore produce a better guess.

In summary:
[user supplied "Use specific value"] — overrides --> [API call supplied hint parameters] — overrides --> [API call supplied "instructions"]


Common task

There are three common API tasks:

  1. Get a list of the current user's exposed actions
  2. Get a list of an action's optional hint parameters
  3. Execute or preview an action

Let's go through each, assuming you have a valid access token already.

1. Get a list of the current user's exposed actions

# via the RESTful list endpoint:
curl -v -H "Authorization: Bearer <ACCESS_TOKEN>" https://actions.zapier.com/api/v1/dynamic/exposed/

# via the dynamic openapi.json schema:
curl -v -H "Authorization: Bearer <ACCESS_TOKEN>" https://actions.zapier.com/api/v1/dynamic/openapi.json

Excerpt of a list endpoint response (see full response):

{
"results": [
    {
        "id": "01GTB1KMX72QTJEXXXXXXXXXX",
        "description": "Slack: Send Channel Message",
        ...

Excerpt of an openapi.json response (see full response):

{
    ...
    "paths": {
        ...
        "/api/v1/dynamic/exposed/01GTB1KMX72QTJEXXXXXXXXXX/execute/": {
            "post": {
                "operationId": "exposed_01GTB1KMX72QTJEXXXXXXXXXX_execute",
                "summary": "Slack: Send Channel Message (execute)",
                ...

2. Get a list of an action's optional hint parameters

As a reminder, hint parameters are always optional. By default, all parameters are filled in via guessing based on a provided instructions parameter. If a hint parameter is supplied in an API request along with instructions, the hint parameter will override the guess.

# via the RESTful list endpoint:
    curl -v -H "Authorization: Bearer <ACCESS_TOKEN>" https://actions.zapier.com/api/v1/dynamic/exposed/

    # via the dynamic openapi.json schema:
    curl -v -H "Authorization: Bearer <ACCESS_TOKEN>" https://actions.zapier.com/api/v1/dynamic/openapi.json

Excerpt of a list endpoint response (see full response):

{
    "results": [
    {
        "id": "01GTB1KMX72QTJEXXXXXXXXXX",
        "description": "Slack: Send Channel Message",
        "input_params": {
            "instructions": "str",
            "Message_Text": "str",
            "Channel": "str",
            ...

Excerpt of an openapi.json response (see full response):

{
    ...
    "components": {
        "schemas": {
            ...
            "PreviewExecuteRequest_01GTB1KMX72QTJEXXXXXXXXXX": {
                "title": "PreviewExecuteRequest_01GTB1KMX72QTJEXXXXXXXXXX",
                "type": "object",
                "properties": {
                    "instructions": {
                        ...
                    },
                    "Message_Text": {
                        ...
                    },
                    "Channel_Name": {
                        ...
                    }

Note: Every list of input params will contain instructions - the only required parameter for action execution.

3. Execute (or preview) an action

Finally, with an action ID and any optional hint parameters in hand, we can run ("execute") an action.

curl -v \
    -d '{"instructions": "send a short poem about automation and robots to slack", "Channel_Name": "#fun-zapier"}' \
    -H "Content-Type: application/json" \
    -X POST 'https://actions.zapier.com/api/v1/dynamic/exposed/01GTB1KMX72QTJEXXXXXXXXXX/execute/'

Another example, this time an action to retrieve data:

curl -v \
    -d '{"instructions": "grab the latest email from bryan helmig"}' \
    -H "Content-Type: application/json" \
    -X POST 'https://actions.zapier.com/api/v1/dynamic/exposed/01GTA3G1WD49GN1XXXXXXXXX/execute/'

One more example, this time requesting a preview of the action:

curl -v \
    -d '{"instructions": "say Hello World to #fun-zapier", "preview_only": true}' \
    -H "Content-Type: application/json" \
    -X POST 'https://actions.zapier.com/api/v1/dynamic/exposed/01GTB1KMX72QTJEXXXXXXXXXX/execute/'

Execution return data

The Status key

The API response to executing an action will contain a status key, which can be one of four values.

1. "success"
The action executed successfully and found results.

2. "error"
The action failed to execute. An error key will have its value populated.

For example:

{
    ...
    "action_used": "Gmail: Send Email",
    "result": null,
    "status": "error",
    "error": "Error from app: Required field \"subject\" (subject) is missing. Required field \"Body\" (body) is missing."
}

3. "empty"
The action executed successfully, but no results were found. This status exists to be explicit that having an empty result is correct.

4. "preview"
The action is a preview and not a real execution. A review_url key will contain a URL to optionally execute the action from a browser, or you can call the endpoint again without the preview_only input parameter.

For example:

{
    ...
    "action_used": "Slack: Send Channel Message",
    "input_params": {
        "Channel": "fun-zapier",
        "Message_Text": "Hello World"
    },
    "review_url": "https://actions.zapier.com/execution/01GW2E2ZNE5W07D32E41HFT5GJ/?needs_confirmation=true",
    "status": "preview",
}

The Result key

All actions will return trimmed result data. result is ideal for humans and language models alike!

By default, full_results is not included, but it can be useful for machines. Contact us if you'd like access to full results.

The trimmed version is created using some AI and heuristics:

  • Selects for data that is plain text and human-readable
  • Discards machine data like IDs, headers, etc.
  • Prioritizes data that is very popular on Zapier
  • Reduces final result into ~500 words

Trimmed results are ideal for inserting directly back into the prompt context of an LLM without blowing up context token window limits.

Example of a trimmed results payload from "Gmail: Find Email":

{
    "result": {
        "from__email": "mike@zapier.com",
        "from__name": "Mike Knoop",
        "subject": "Re: Getting setup",
        "body_plain": "Hi Karla, thanks for following up. I can confirm I got access to everything! ... Thanks! Mike",
        "cc__emails": "bryan@zapier.com, wade@zapier.com"
        "to__email": "Mike Knoop",
    }
}

Great job!

You made it through the most dense page in the AI Actions docs. 🏆