# Save an audience

> save_audience: Saves an audience definition under a name, shared across the organisation, or updates a saved one when audience_id is given.

Source: https://emailmovers.com/mydatahub/docs/reference/mcp/save_audience

Saves an audience definition under a name, shared across the organisation, or updates a saved one when audience_id is given. Use it when the user wants to keep, share or recount a list later; saving is free and needs audiences:write. Repeating the same call returns the same saved audience. Call list_audiences to find it again, or count_audience with its aud_ id. Lawful basis is UK GDPR Article 6(1)(f) legitimate interests; email audiences include corporate subscribers only by default (PECR), so sole traders and ordinary partnerships are left out unless the toggle is changed.

| Property | Value |
| --- | --- |
| Tool name | `save_audience` |
| Position in tools/list | 10 of 22 |
| Cost | Free |
| Scope | `audiences:write` |
| Annotations | readOnlyHint false, destructiveHint false, idempotentHint true, openWorldHint false |
| Kind | Write; idempotent, not destructive, closed world |
| REST equivalent | [`POST /v1/audiences`](https://emailmovers.com/mydatahub/docs/reference/rest/create-audience.md); [`PATCH /v1/audiences/{id}`](https://emailmovers.com/mydatahub/docs/reference/rest/update-audience.md) |

> **Not yet live.** MyDataHub v2 is built and tested locally and is not yet live. The v2 hosts open at launch, date to confirm. This is what `tools/list` returns from https://mydatahub.emailmovers.com/mcp once v2 launches.

## Input

The schema sets `additionalProperties` to false, so a member that is not listed is refused.

| Member | Type | Required | Description |
| --- | --- | --- | --- |
| `audience_id` | string | no | A saved audience to update. Leave it out to save a new one. |
| `name` | string | no |  |
| `audience` | `Audience` | no | Who you want, as filters grouped by entity (company., site., contact., email., phone., signal.). The server fills its defaults (active companies, named emails, corporate subscribers, the current dataset_version) and returns the effective definition with every count. See [Audience](https://emailmovers.com/mydatahub/docs/audience.md). |
| `brief` | string or null | no |  |

## Example call

The `params` of a `tools/call` request:

```json
{
  "name": "save_audience",
  "arguments": {
    "name": "Marketing directors, Leeds",
    "audience": {
      "schema": "mydatahub.audience/1",
      "dataset": "uk_contacts",
      "dataset_version": "2026-W39",
      "where": {
        "all": [
          {
            "field": "contact.title",
            "op": "matches",
            "terms": ["marketing manager"],
            "mode": "contains",
            "expand": ["plural_singular", "department_synonyms", "ampersand_and", "abbreviations"]
          },
          {
            "field": "contact.job_level_rank",
            "op": "in",
            "values": [1, 2, 3, 4, 5, 6, 8, 9]
          },
          {
            "field": "company.sic_2007",
            "op": "in",
            "values": ["C"]
          },
          {
            "field": "company.employee_band",
            "op": "gte",
            "value": "50-99"
          },
          {
            "field": "site.location",
            "op": "within_radius",
            "centre": {
              "place": "Leeds"
            },
            "radius_miles": 20
          },
          {
            "not": {
              "field": "email.address_sha256",
              "op": "in_list",
              "list_id": "sup_01JB4H7Q2V7XN3M9R6T1Y5W8ZA"
            }
          }
        ]
      },
      "email_policy": {
        "min_deliverability_score": 70,
        "allow_catch_all": false
      },
      "dedupe": "none"
    }
  }
}
```

## Output

The result carries `structuredContent` that matches this schema, and one line of text that leads with the number.

| Member | Type | Always present | Description |
| --- | --- | --- | --- |
| `id` | string | yes | Format: an audience id: aud_ followed by a 26 character ULID in upper case Crockford base32, such as aud_01JB4H2K9V6XN3M9R6T1Y5W8ZA. |
| `name` | string | yes |  |
| `audience` | `Audience` | yes | Who you want, as filters grouped by entity (company., site., contact., email., phone., signal.). The server fills its defaults (active companies, named emails, corporate subscribers, the current dataset_version) and returns the effective definition with every count. See [Audience](https://emailmovers.com/mydatahub/docs/audience.md). |
| `brief` | string or null | yes | The brief it was compiled from, if any. |
| `current_count` | `AudienceCountSummary` or null | yes |  |
| `current_count.count_id` | string | yes | Format: a count id: cnt_ followed by 20 base32 characters (A to Z and 2 to 7), such as cnt_7K2PQ4MAXN3R6TBY5WDZ. |
| `current_count.dataset_version` | string | yes | The immutable weekly build a count is bound to, such as 2026-W39. The last 52 stay queryable. |
| `current_count.contacts` | integer (0 or more) | yes |  |
| `current_count.companies` | integer (0 or more) | yes |  |
| `current_count.emailable` | integer (0 or more) | yes |  |
| `current_count.counted_at` | string (date-time) | yes |  |
| `last_refreshed_at` | string (date-time) or null | yes |  |
| `created_at` | string (date-time) | yes |  |
| `updated_at` | string (date-time) | yes |  |
| `created_by` | string | yes | Format: a user id: usr_ followed by a 26 character ULID in upper case Crockford base32, such as usr_01JA0Q3V7XN3M9R6T1Y5W8ZAK8. |
| `url` | string (uri) | yes | The audience in the app, mydatahub.emailmovers.com/audiences/{id}. |

## Errors

A failed call returns `isError` true. The text content leads with the sentence a person acts on, then the whole problem as JSON, with `code`, `detail`, `next_step` and `did_you_mean`. A 401 and a step-up 403 are answered at HTTP level so the client can start authorisation. See [Errors](https://emailmovers.com/mydatahub/docs/errors.md).
