> ## Documentation Index
> Fetch the complete documentation index at: https://help.avoca.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Import audiences

> Create an outbound audience from JSON contacts without uploading a spreadsheet.

Send a complete contact list to Avoca, then select **Existing Audience** when
creating a campaign in the dashboard. Importing contacts does not create,
launch, or extend a campaign. No CRM customer or lead record is required.

## 1. Create an API key

In the dashboard, open your team and go to **Integrations → API Keys**.
Select **Create API Key** and enable **Import audiences** (`write:audiences`)
and **Read audiences** (`read:audiences`). Copy the key when it is shown;
the full key is displayed only once.

Creating team API keys requires a team admin account and enterprise access.
If you cannot access this page, ask your team admin to set up the key.
See [Authentication & Permissions](/api-reference/authentication) for other key types.

Your numeric team ID is the number after `/team/` in the dashboard URL.
The team in an API request must be within the key's team, enterprise, or
portfolio scope.

## 2. Send your contacts

`POST /api/v1/teams/{teamId}/audiences`

These endpoints use **`https://api.prod.avoca.ai`**. In the example below,
replace `YOUR_TEAM_ID`, `YOUR_API_KEY`, and the sample contact with your values.
Include each contact's actual ZIP if your team has service areas configured.

Use a new `Idempotency-Key` for each new list. To retry the same import, keep
the key and body unchanged. Keys can contain
letters, numbers, dots, underscores, colons, and hyphens, up to 200 characters.

```bash theme={null}
export TEAM_ID="YOUR_TEAM_ID"
export AVOCA_API_KEY="YOUR_API_KEY"

curl -X POST "https://api.prod.avoca.ai/api/v1/teams/$TEAM_ID/audiences" \
  -H "Authorization: Bearer $AVOCA_API_KEY" \
  -H "Idempotency-Key: september-generator-list-1" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "September generator leads",
    "exclude_recently_contacted_days": 45,
    "members": [{
      "customer_name": "Example Customer",
      "customer_phone": "+12025550123",
      "customer_email": "customer@example.com",
      "customer_address_street": "123 Example Street",
      "customer_address_city": "Washington",
      "customer_address_state": "DC",
      "customer_address_zip": "20001",
      "business_unit": "Generators"
    }]
  }'
```

## 3. Check the result

**Success — HTTP 201:**

```json theme={null}
{
  "data": {
    "audience_id": 123,
    "name": "September generator leads",
    "member_count": 1,
    "duplicates_skipped": 0,
    "excluded_count": 0
  }
}
```

Import applies the same initial eligibility filter as spreadsheet uploads:
team exclusions, the recent-contact window, and configured service-area ZIPs.
If your team has service areas, include a matching ZIP for each contact.
`excluded_count` reports unique contacts removed by that filter;
`member_count` is the number saved. A fully excluded list has zero members.

## 4. Use the audience in a campaign

When the import succeeds, open outbound campaign creation in the dashboard.
Choose **Existing Audience** and select the audience by the name you submitted.
Review the saved contacts, current exclusions, and outreach settings, then
launch through the dashboard when ready. The API import itself does not send
messages or make calls.

## Contact fields

| Field                               | Required | Limit                                                                      |
| ----------------------------------- | -------- | -------------------------------------------------------------------------- |
| `name`                              | Yes      | 1–200 characters                                                           |
| `exclude_recently_contacted_days`   | No       | Integer 0–365; defaults to 45. Use 0 to disable the recent-contact window. |
| `members`                           | Yes      | 1–1,000 contacts; maximum request body 1 MiB                               |
| `members[].customer_name`           | Yes      | 1–200 characters                                                           |
| `members[].customer_phone`          | Yes      | Valid +1 E.164 number, such as `+12025550123`                              |
| `members[].customer_email`          | No       | Valid email, up to 254 characters                                          |
| `members[].customer_address_street` | No       | Up to 300 characters                                                       |
| `members[].customer_address_unit`   | No       | Up to 100 characters                                                       |
| `members[].customer_address_city`   | No       | Up to 100 characters                                                       |
| `members[].customer_address_state`  | No       | Up to 100 characters                                                       |
| `members[].customer_address_zip`    | No       | Up to 20 characters                                                        |
| `members[].business_unit`           | No       | Up to 200 characters                                                       |

Optional contact fields may be omitted, empty, or null. Unknown fields are rejected.
Each contact takes one phone number. If a phone appears more than once, the
first contact wins and the remaining rows count toward `duplicates_skipped`.
Any invalid row rejects the entire request; no partial audience is created.

## Retry behavior

Retry a timeout or server error with the **same key and request body**. Within
24 hours, successful retries return the original audience and set
`X-Idempotency-Replayed: true`. Reusing the key with a different body returns
409\. Keys are scoped to the team, so rotating an API key does not duplicate a
completed import. After 24 hours, a retry can create a new audience.

Each new import creates a separate audience. This API does not update an
existing list or change recipients of an existing campaign. Lists over 1,000
contacts should use the existing spreadsheet import flow.

## Retrieve an audience

`GET /api/v1/teams/{teamId}/audiences/{audienceId}`

Use the returned `audience_id` to retrieve the name, current member count, and
archive status. This also works for spreadsheet audiences. The key needs
`read:audiences`.

```bash theme={null}
export AUDIENCE_ID="ID_FROM_IMPORT_RESPONSE"

curl "https://api.prod.avoca.ai/api/v1/teams/$TEAM_ID/audiences/$AUDIENCE_ID" \
  -H "Authorization: Bearer $AVOCA_API_KEY"
```

```json theme={null}
{
  "data": {
    "audience_id": 123,
    "name": "September generator leads",
    "member_count": 1,
    "is_archived": false
  }
}
```

## Errors

| Status | Meaning                                                                               |
| ------ | ------------------------------------------------------------------------------------- |
| 400    | Invalid input or missing/invalid `Idempotency-Key`; row errors include the field path |
| 401    | Missing, invalid, revoked, or unsupported API key                                     |
| 403    | Missing audience permission or team outside the key's scope                           |
| 404    | Audience not found in the team's imported audiences                                   |
| 409    | Idempotency key already used for a different request                                  |
| 500    | Import failed; retry with the same key and body                                       |
