This article describes how you can use custom APIs inside of workflows. This allows you to integrate external services and have your AI agent take actions.

Using custom API endpoints, you can build a workflow that finds recent order details, automatically updates a customer's account, and many other actions.

## Prep work: Prepare your endpoints

Before you start building a workflow with custom APIs, it's good to gather all the relevant information needed to call the APIs you're planning on using. That can include:

- Domain
- Endpoint
- Authorization Method
- HTTP Method
- Content Type Format
- Request Body Schema (if required)
- Expected Response Body Schema

## Step 1: Add your API domains

API endpoints are first set up in the main Assembled settings page, which allows them to be stored/updated in a central place and re-used in multiple workflows

This starts by adding the base domains of the various endpoints you're planning to use.

To add a new domain - go to **Configure** \> **AI Agent Setup** \> **Tools and connectors** \> **Manage domains**.

You can add as many domains as you’d like. When adding a domain, you’ll also set up headers needed for the endpoint. Common headers may include:

- `Authorization`
- `Content-Type`

Headers are simply key-value pairs, so you should provide this data as if you were making a raw request. For example, an API that uses a bearer token for auth may be set to `Authorization`: `Bearer {token_value}` .

You can also set custom Headers on a per-endpoint level, so make sure to only include any Headers that are needed across all endpoints you plan to call.

## Step 2: Define your endpoints

Now that you’ve defined your domain, you can add all endpoints that you want to send requests to.

To start - close the **Manage domains** pop-up box and click **Configure new API endpoint**. In the sidebar, you'll be able to set up your endpoint:

`Name` \- The name you want to give the endpoint (This is what we'll show in the workflow builder)

`Method` \- The API request method (GET, POST, DELETE, etc)

`Domain` \- The domain you want to use for this endpoint (Created in Step 1)

`Path` \- The specific endpoint you want to call from the domain

- You can use variables within the endpoint path using template values
- For example, if your path is `/orders/{{order_id}}` , `order_id` will act as a variable. Within workflows, you can define this variable in steps before the API call. So, if you define `order_id` as “14326” in the automation, your path will become `/orders/14326`.
- Refer to **Step 3** for more information on variables

`Additional headers` \- Optional. Allows you to add custom headers specific to that endpoint.

- For example, if a single domain uses different Content-Types across its endpoint - you may want to define that at an Endpoint level

`Request body` \- Optional. Allows you to send data to the endpoint via Request Body text.

- You can also set up custom request bodies per workflow. So if you want to re-use the same endpoint but make different requests in different workflows, leave this blank for now.
- Request bodies also support variables, like the Path field

After you've set up your end point - you can send a test request to make sure everything works.

_Please note - Testing your endpoint makes a real API call, so please test with example data where possible when using POST or DELETE calls._

Click **Save API endpoint** to save your endpoint.

## Step 3: Use your endpoints in a workflow

Now that you’ve built your endpoint, you’re ready to add it to a workflow!

Assuming you’ve built one before, you’ll start by building a workflow like any other. If you haven't built one before, you can learn more about [Building workflows here](https://support.assembled.com/hc/en-us/articles/35510271542541-Building-workflows).

### Step 3A: Set up all steps before the API request

Your workflow steps should be set up in the order that you want the agent to work through them.

That means if your API requires dynamic variables to work correctly, you'll need to use steps before the API step to collect the relevant data.

For example, you may want to use a **Zendesk Data Lookup** step to grab the customer's email and store it in an `{{email}}` variable. Or, you may want to use a **Analyze Case** step to look for a customer's Order number in their message.

### Step 3B: Custom API step

Once you're ready - you can add **Custom API Tool** step to the workflow.

#### Type

The **Type** dropdown lets you choose whether the API is a lookup (`Read`) call, or if it will actually modify (`Write`) data when called.

This is useful when testing - as you'll be able to choose whether or not you want `Write` API calls to run during tests. Disabling Write calls while testing helps prevent accidentally adding or deleting data in your production environment.

#### Request Body

If you didn't set up a "default" request body earlier - you'll be able to add a request body at this step. In the request body - you can use static values or call variables with the format `{{variableName}}`.

By default, variables are sent as a string value. If you want to send an `int`, `boolean`, or `float` value you can use the format `{{variableName: type}}`.

For example, here's the request body for a `POST` request you might make:

```json
{
	"name": "Cal",
	"email": {{email}},
	"inquiry": {
		"message": {{message}}
		"orderId": {{order_id: int}}
	}
}
```

In this example, you’ll need to ensure that the `email`, `message`, and `order_id` variables were all created earlier in the workflow. This can be done with a Lookup step, Analyze Case step, a Guide step, or even another custom API step.

_Please note - in this example, the static_`string` _value "Cal" is wrapped in quotation marks ("0)._`String` _variables are automatically sent with the necessary quotations, so you can just leave those as_`{{variable}}`

#### Output Variables

If your API generates a response - you may want to store that data in variables to be used in future workflow steps. Output variables are created by mapping your request response to any relevant variable names.

For example, if you had the following response:

```json
{
	"status": "closed",
	"order_id": "5678",
	"fulfillment": {
		"tracking_number": "90322321312"
	}
}
```

You can define new variables and map it to values from this response. In this example, you can grab the status and tracking using the following Paths:

| Output variables | Path |
| --- | --- |
| status | status |
| trackingNumber | fulfillment.tracking_number |

You can also use the path `.` to store the entire response, which can then be parsed all at once using Guide steps.

## Advanced use cases

### Using OAuth in workflows

We don't currently have native support for OAuth as an API authorization method.

However, many OAuth APIs provide an endpoint to generate a time-limited access token using a POST request. This can be a workaround for some simple workflows. To set that up:

1. First, you would use the domain's token endpoint and store the output in a variable.
2. Then, you can reference that variable in the header of future requests within the same workflow.

_Please note - variables are only stored for the duration of a workflow. So you can't currently use the same authorization token across multiple workflow runs._

### Setting up `x-www-form-urlencoded` API calls

We fully support APIs that require their `Content-Type` of the request body to be sent in the `x-www-form-urlencoded` format, but setting up these API calls can be tricky.

To set up these API calls:

1. First, ensure you set the `Content-Type` to `application/x-www-form-urlencoded` when adding your Headers.
2. In the request body, you can add your key:value pairs in a JSON format.
   - For example, `grant_type= client_credentials&client_id={{client_id}}&client_secret={{client_secret}}` turns into:

```json
     {
       "grant_type": "client_credentials",
       "client_id": {{client_id}},
       "client_secret": {{client_secret}}
     }
     ```
3. While this isn't the standard format for a `urlencoded` request, our system will automatically convert the JSON into the correct format when the API is called.

Currently, when you set up a `urlencoded` API, the **Test endpoint** button on the configuration page might not work. Instead, it may show a `500 Error` response. This happens because the **Test endpoint** button doesn't automatically convert the `JSON` format into the x-`www-form-urlencoded` format.

**Rest assured - if your JSON is set up correctly, the API will work in workflows.** You can test these APIs by setting up a test workflow and using a **Chat Preview**. There, you'll see the API response in the sidebar.
