# Custom Audience Setup Guide


{{< customreadfile "/includes/audiences/private-beta-callout.md" >}}

Use this guide to set up a Custom Audience destination in RudderStack.

To sync a saved audience to your Custom Audience destination, see [How to Sync Audiences to Custom Audience]({{< ref "audiences/syncs/custom-audience/sync-audiences.md" >}}).

## Setup

1. Go to **Collect** > **Destinations** > **New Destination**.
2. Search and select **Custom Audience**.
3. Creating a source is **optional**. Click **Continue** to skip this step.
4. Configure the following settings to specify how RudderStack connects to your API and complete the setup:

| Setting | <div style="width: 350px;">Description</div> |
| :--- | :--- |
| Name | A unique name that identifies this destination in your workspace. |

### Audience delivery API configuration

| Setting | <div style="width: 350px;">Description</div> |
| :--- | :--- |
| Enter base URL | Specify the root URL for your API (for example, `https://api.example.com`). All requests are sent to this URL. |
| Specify authentication | Choose how RudderStack authenticates with your API. <br /><br />See [Authentication](#authentication) section below for details. |
| Custom headers | This **optional** setting lets you add extra key-value headers to every request (for example, `Content-Type`, `X-API-Version`). |

#### Authentication

| Method | <div style="width: 350px;">Description</div> |
| :--- | :--- |
| No authentication | None — use this for public endpoints only |
| Basic Auth | Enter a username and password |
| API Key | Specify a header name (for example, `X-API-Key`) and API key value |
| Bearer Token | Enter a bearer token value |

### Endpoint configurations

Configure how RudderStack **adds**, **updates**, and **removes** audience members:

| Setting | When it runs |
| :--- | :--- | 
| **Add record** | A user enters the audience |
| **Update record** | A member's mapped attributes change. <br /><br />{{< tip >}}Set **Use Add record configuration** to **Yes** to reuse the same method, path, template, and fields as **Add record**.{{< /tip >}} |
| **Remove record** | A user leaves the audience |

{{< image src="images/audiences/destinations/custom-audience/use-add-record-configuration.webp" alt="Use Add record configuration" >}}

### Action-specific settings

Each action's (add/update/remove record) settings follow the same structure.

#### HTTP method and endpoint path

| Setting | Description |
| :--- | :--- |
| HTTP method | `POST`, `PUT`, `PATCH`, `GET`, or `DELETE` for this action. |
| Endpoint path URL | Path appended to the [base URL](#audience-delivery-api-configuration). <br /><br />It supports simple interpolation with connection values, for example `/audiences/{{connection.audienceId}}/members`. |

{{< info >}}
The resolved URL is the base URL plus the evaluated endpoint path.
{{< /info >}}

#### Batch size

| Setting | Description | Default value |
| :--- | :--- | :----| 
| Batch size | Maximum records per HTTP request for this action. Range **1**–**5000** | 5000 | 

#### Request body template

Define the JSON body sent to your API. The template follows [JSONata syntax](https://docs.jsonata.org/overview.html).

{{< info >}}
Templates are validated when you save the destination. An invalid syntax is rejected with an error that identifies the action and issue.
{{< /info >}}

A sample request body template is shown below:

```json
{
  "audience_id": $$.connection.audienceId,
  "elements": [$$.records.{
    "userIds": [
      {"idType": "SHA256_EMAIL", "idValue": sha256_email},
      {"idType": "GOOGLE_AID", "idValue": google_aid}
    ],
    "firstName": first_name,
    "lastName": last_name,
    "nested": {
      "org": "static_value"
    }
  }]
}
```

**Global objects available at runtime**

| Object | <div style="width: 350px;">Description</div> |
| :--- | :--- |
| `$$.records` | Array of records in the current batch (after field processing and hashing) |
| `$$.connection` | Sync connection metadata, including `audienceId` |

**Allowed operations**

- Object and array construction
- Path expressions (`$$.records`, `$$.connection.audienceId`)
- Iteration with `{ ... }` — for example, `$$.records.{ "email": email, "user_id": user_id }`
- String, number, and boolean literals
- `Number()` casting where needed, for example,`$number($$.connection.audienceId)`

#### Template example

A template for generic batched members is shown below:

```json
{
   "audienceId": $$.connection.audienceId,
   "users": [$$.records.{
    "email": email,
     "user_id": user_id
  }]
}
```

#### Template fields

After you define a template, RudderStack extracts field names referenced under `$$.records` and lists them under **Template fields**. Click **Refresh** to re-scan the template, or **Manage fields** to configure each field.

{{< image src="images/audiences/destinations/custom-audience/template-fields.webp" alt="Manage template fields" >}}

| Field setting | Description |
| :--- | :--- |
| Name | Destination-side field name used in the template |
| Required | If enabled, you must map the field to a warehouse column during [sync setup]({{< ref "audiences/syncs/custom-audience/sync-audiences.md#map-identifiers" >}}) |
| Static | If enabled, the value is a literal you provide while [adding a sync]({{< ref "audiences/syncs/custom-audience/sync-audiences.md#map-identifiers" >}}) |
| Hash | Hash algorithm applied before the template runs. You can choose between **None**, **SHA256**, **SHA512**, or **MD5**. |

{{< image src="images/audiences/destinations/custom-audience/configure-fields.webp" alt="Configure template fields" >}}

{{< warning >}}
If you rename or remove template fields after syncs exist, make sure to update mappings on each affected sync manually. 

See [Troubleshooting]({{< ref "audiences/syncs/custom-audience/sync-audiences.md#troubleshooting" >}}) for more information.
{{< /warning >}}

### Request preview

Use **Fetch preview** to build a sample HTTP request from test records. 

{{< info >}}
Preview does not send traffic to your API.
{{< /info >}}

1. Choose how many sample records to include (for example, **1 record**).
2. Edit sample data if needed.
3. Click **Fetch preview** to see the resolved method, URL, headers, and JSON body.

{{< image src="images/audiences/destinations/custom-audience/fetch-preview.webp" alt="Fetch preview" >}}

## Troubleshooting

| Issue | <div style="width: 350px;">Resolution</div> |
| :--- | :--- |
| Template is rejected on save | The syntax is outside the [allowlisted operations](#request-body-template) — the error message names the action and position |
| Unexpected payload shape | Use the [Fetch preview](#request-preview) with the same sample records and action type (`INSERT`, `UPDATE`, or `DELETE`) to verify the payload shape |

## Next steps

To sync a saved audience to your Custom Audience destination, see [How to Sync Audiences to Custom Audience]({{< ref "audiences/syncs/custom-audience/sync-audiences.md" >}}).

<br />
