# Changelog


<div style="margin-top:0.5rem;margin-bottom:1.5rem;">
{{< hextra/hero-subtitle >}}
  What's new in the Intuizi API, the MCP server, the CLI, and the console.
{{< /hextra/hero-subtitle >}}
</div>

Notable changes, newest first, since the first generally available release.
This page shows the latest month in full, and every earlier month has a page
of its own.

Each change is tagged with what it affects:

- {{< products "API" >}} the REST API. The MCP server and the CLI call the
  API, so they get these changes too.
- {{< products "MCP" >}} the MCP server, its tools, or connecting an MCP
  client.
- {{< products "CLI" >}} the Intuizi CLI.
- {{< products "Console" >}} the Intuizi console.

## September 2026

### 2026-09-27

- **Size estimates, activation preview, and the visualization catalog in the CLI** {{< products "CLI" >}}

  CLI v0.1.6 adds a command for each of the four API reads that had none.
  `intuizi audiences estimate create` sizes an audience from the same flags or
  `--file` body as `audiences create` without creating it, and
  `intuizi audiences estimate show <id>` reads the result, both with `--wait`.
  `intuizi activations preview` counts the devices a frequency range would
  deliver and prints the histogram and the `filter_hash`, and
  `intuizi reference common datastream-visualizations` lists the data stream
  visualizations an audience can draw. `audiences create` and
  `audiences estimate create` take `--frequency` to run the dataset type's
  frequency analysis, and `activations create` takes `--freq-min`,
  `--freq-max`, and `--filter-hash`, so a previewed range can be delivered
  without a `--file` body. See
  [Estimate create](/cli/reference/audiences#estimate-create) and
  [Preview](/cli/reference/activations#preview).

- **Estimate Audience Size is listed as idempotent** {{< products "API" >}}

  [Idempotency](/concepts/idempotency) now lists
  [Estimate Audience Size](/api/v2/audiences#post-apiv2analysesaudiencesestimate),
  which already read the `Idempotency-Key` header, so eight endpoints honor
  it. A retry with the same key and body replays the estimate rather than
  scanning the data again.

- **A build that stops at `107` Additional Info now sends the failed webhook** {{< products "API" >}}

  An audience or activation that Intuizi stops at `107` Additional Info,
  because it cannot be built as defined, now sends `audience.failed` or
  `activation.failed` to every [webhook](/concepts/webhooks) endpoint
  subscribed to it, once, with the same payload as a `4xx` failure. Read
  `data.status.id` to tell them apart. The payload carries only the status id
  and name, and Audience Manager shows the reason for a `107`. Until now a
  build that stopped at `107` sent no event, and only a read showed it. See
  [Webhook event payloads](/api/v2/webhooks#audience-events).

- **A cancelled Lookalike Model now ends at `400` Error** {{< products "API" "Console" >}}

  A run cancelled with
  [Cancel Lookalike](/api/v2/audiences#post-apiv2analysesaudiencescancel-lookalike)
  used to read `108` Modeling for good once it stopped, so a poll or a
  `--wait` on it could only time out. It still stops at its next checkpoint,
  and then ends at `400` Error, which is final and sends an
  [`audience.failed`](/api/v2/webhooks#audience-events) webhook. Audience
  Manager shows it as `Cancelled on request.` A cancel that arrives once the
  result is already being published is still ignored, and the run completes
  at `104`. A run that had already stopped on a cancel before this date keeps
  reading `108`.

- **A failed cohort import now reports `5` Not Available** {{< products "API" >}}

  A failed import used to end at an error code outside the
  [cohort status scale](/concepts/status-codes#3-cohort-status-scale-1-5),
  which [Get Cohort](/api/v2/cohorts#get-apiv2analysescohortsid) named
  `Unknown`, and it sent no webhook. It now ends at `5` Not Available and
  sends [`cohort.failed`](/api/v2/webhooks#cohort-events), so a cohort goes
  `1` to `4` on success and ends at `5` on failure. A cohort that failed
  before this date keeps the code it failed with, still named `Unknown`.

- **A scheduled Origin audience moves with each cycle** {{< products "API" >}}

  Every cycle of a [schedule](/api/v2/schedules#how-schedules-work) restamps
  the audience's datasets to that cycle's data window, but an Origin dataset
  kept the weeks it was built with, so a scheduled Origin audience rebuilt the
  same data every cycle. An Origin dataset now gets each cycle's window too,
  widened to the whole Monday-to-Sunday weeks it touches, the same widening
  [Create Audience](/api/v2/audiences#post-apiv2analysesaudiencescreate)
  applies. This applies from the next cycle of every schedule, including
  schedules created before this date. A cross purchase block still keeps the
  dates it was built with.

- **A schedule's end date cannot come before its start** {{< products "API" "Console" >}}

  [Create Schedule](/api/v2/schedules#post-apiv2analysesschedulescreate)
  accepted a `recurrence.ending.end_date` earlier than the date of
  `recurrence.start` and counted the gap forward: a daily schedule starting
  `2030-01-15 09:00:00` with an end date of `2030-01-10` was stored with 6
  runs instead of being refused. It is now rejected with `422`, naming
  `recurrence.ending.end_date`. The start's own date is still accepted and
  gives one run. The Scheduler in Audience Manager applies the same rule, and
  the CLI already refused such an `--end-date` before sending it.

- **A monthly Custom Date schedule counts calendar months** {{< products "API" "Console" >}}

  A monthly schedule runs one calendar month apart, but
  [Create Schedule](/api/v2/schedules#post-apiv2analysesschedulescreate)
  turned its `Custom Date` ending into a run count using 30-day periods, so
  near the end date the count was off by one run or more. Monthly from
  `2026-10-15 06:00:00` to `2027-10-15` stored 13 runs, the last on
  `2027-10-15 06:00`, after the end date. `recurrence.cycles.available` now
  counts the calendar-month runs up to 00:00 on `end_date`: 12 in that
  example, the last on `2027-09-15`. Schedules created in Audience Manager
  count the same way, and `daily`, `weekly`, and `bi-weekly` counts are
  unchanged. The count is set when a schedule is created, so a monthly
  `Custom Date` schedule created before this date keeps its stored count.

- **A POI submission with `remove` archives exactly the POIs it does not list** {{< products "API" >}}

  `remove` was applied 250 locations at a time. On a longer submission, POIs
  listed after the first 250 were archived and then added again with new ids,
  and locations the submission had just added were archived. A submission in
  which no location matched archived nothing. The three
  [submission creates](/api/v2/poi/submissions#post-apiv2my-datapoissubmissionscreate-by-file),
  and `intuizi poi submissions create --remove`, now apply `remove` once, after
  every location has been matched: every POI the brand had that no location
  matches is archived, the matched POIs keep their ids, and the locations the
  submission adds are kept. A `remove` submission whose locations carry
  values for its `key` but match no POI now archives every POI the brand had
  (one that holds no location at all, or in which no location has a value for
  its `key`, archives nothing), so list every location the brand should keep.
  If an approval is interrupted part way, its locations are still imported
  but `remove` is not applied, and sending the submission again applies it.
  This applies to every submission approved from this date.

- **The `location-id` key matches on `location_id`** {{< products "API" >}}

  A location's `location_id` was dropped when a submission was read, so with
  `key` set to `location-id` the location was added a second time, and
  `update` or `remove` could act on an unrelated POI of the brand. A location
  now matches the brand's POI whose id is its `location_id`. One with no
  `location_id`, or with one that is not the id of one of the brand's POIs, is
  added as a new POI. A `remove` submission in which no location has a
  `location_id` names no POI to keep, so it archives nothing. A `location_id`
  must be the `id` of one of your POIs, and a file may write it as a whole
  number with or without `.0` (`101` or `101.0`). A `location-id` submission
  created before this date was read without its `location_id` values, so if
  it is still `Waiting`, delete it and send it again. See the
  [matching note](/api/v2/poi/submissions#post-apiv2my-datapoissubmissionscreate-by-file).

- **A null `key` on a POI submission means `gps-coordinates`** {{< products "API" >}}

  A `key` sent as null (or as an empty form field) was stored as null, and the
  approval then matched every location to the brand's first POI: nothing was
  added, `update` rewrote that one POI, and `remove` archived all the others.
  The three submission creates now store it as `gps-coordinates`, the default
  when `key` is left out, and a submission stored with a null `key` is matched
  on `gps-coordinates` too.

- **The MCP `create_poi_submission` tool is marked destructive** {{< products "MCP" >}}

  With `remove`, approving the submission archives every POI of the brand
  that no listed location matches, so the tool now declares
  `destructiveHint: true`, and MCP clients that honor the hint ask for
  confirmation before calling it. Its `update`, `remove`, and `key` fields are
  now described. See the [tools reference](/mcp/tools-reference).

### 2026-09-26

- **A Custom Date schedule runs every cycle up to its end date** {{< products "API" >}}

  A schedule created with the `Custom Date` ending stopped after its first
  cycle: its cycle count was stored as a negative number, so it became
  `Fulfilled` as soon as the first run finished.
  [Create Schedule](/api/v2/schedules#post-apiv2analysesschedulescreate) now
  stores the intended count in `recurrence.cycles.available`: one cycle for
  `recurrence.start` plus one for every full frequency period (1, 7, 14, or 30
  days) in the whole days between the start and 00:00 on `end_date`. A weekly
  schedule from `2026-10-15 06:00:00` to `2027-01-01` now runs 12 cycles
  instead of 1. The count is set when a schedule is created, so a
  `Custom Date` schedule created before this date keeps its stored count. To
  run one to its end date, recreate it with a `recurrence.start` in the
  future. `Never` and `Recurrences` endings are unchanged.

- **Documentation for the Intuizi CLI** {{< products "CLI" >}}

  A new [CLI](/cli) section covers the Intuizi CLI v0.1.4, which runs API v2
  from a terminal, a script, or a CI job. Every command that calls the API is
  built on the documented endpoints and returns their responses under the
  same rate limits. Names are looked up in the catalogs, and flags are checked
  before anything is created. The section covers installing and logging in, a
  quickstart that reads the catalogs then builds and delivers an audience, and
  a command reference listing every command and flag, with the endpoint
  behind each one that calls the API.

- **Upgrading to CLI v0.1.4** {{< products "CLI" >}}

  However v0.1.3 or earlier was installed, v0.1.4 changes the following.
  `activations create` takes `--datastream`, without which an activation built
  from flags delivers nothing. `--debug` prints every HTTP request and
  response on stderr. `audiences create` accepts `--type origin`, and a
  WebDomain `--category` name now sends the category's numeric id, which
  Create Audience takes, rather than its IAB code, which it refused. `--wait`
  keeps waiting while an audience draws its data stream visualizations
  (`109`) and ends as a failure on `107` Additional Info, where earlier
  versions failed on `109` and waited on `107` until the timeout. A wait that
  fails, times out, or gives up prints the last record read on stdout, so
  branch on the exit code. The next `auth login` moves a token stored in the
  config file to the OS credential store, where there is one. `auth status`
  names the account for a token minted by v0.1.4, and reports it as `unknown`
  for one stored by an earlier version until `auth login --email` mints a new
  one. On a `429` the CLI says on stderr each time it waits and retries,
  returns a `429` that asks for more than 60 seconds at once rather than
  retrying into a second refusal, and names the `Retry-After` in the error. A
  `cohorts create --upload-reference` refused by the build budget is not
  retried, since the refusal already used the reference. With `--json`,
  `--wait` prints the server's envelope on every outcome, a timeout and a
  give-up included, and a give-up names the `show <id> --wait` that resumes
  it. `INTUIZI_NO_KEYRING=0` or `false` now leaves the credential store on.
  The npm launcher passes a SIGTERM sent to it on to the binary. New usage
  errors, caught before anything is sent: a schedule `--end-date` before its
  `--start` date, a schedule `--name` over 255 characters, and a schedule
  `--timezone` outside a region (`US/Eastern`, `GMT`, or an `Etc/` name). So
  are an `audiences create --type` the flags cannot build, which `--help`
  names, a `--contrast-audience-id` that is the seed,
  `reference web iab-subcategories --category-ids` mixing ids and codes, and
  `--project-id` with `cohorts create --audience-id`. A WebDomain `--category`
  given an exact IAB code or name, such as `IAB1`, resolves instead of listing
  every code that contains it. `poi submissions create --list` notes on
  stderr each body value a flag replaces, and its `--update=false` and
  `--remove=false` now turn off a `true` in the body. `schedules activate`
  notes a schedule that has made every run its ending allows. See
  [Conventions](/cli/reference#conventions) and
  [Login](/cli/reference/auth#login).

### 2026-09-25

- **Build budget on worker-bound creates** {{< products "API" "Console" >}}

  Every create that starts a worker job (audiences, estimates, Lookalike
  Models, cohorts, and activations) counts against one rolling budget per
  organization, 60 an hour and 300 a day by default, counted across the
  console, the API, and MCP. Scheduled replays do not count. Over the budget,
  the create is refused with `429` and a `Retry-After` header, and nothing is
  created. [Get Usage](/api/v2/usage#get-apiv2usage) returns a new
  `build_budget` object with the limits, the live counts, and
  `retry_after_seconds`. See [Limits & Quotas](/concepts/limits#build-budget).

- **Create Activation enforces the data-scan limit** {{< products "API" >}}

  [Create Activation](/api/v2/activations#post-apiv2analysesactivationscreate)
  now runs the same monthly data-scan check as Create Audience. A company that
  has reached its enforced limit is refused with `422`, and no activation is
  created or queued. Companies without an enforced limit are unaffected.

### 2026-09-24

- **Every frequency analysis on Create Audience** {{< products "API" "MCP" >}}

  The `analyses` object now takes each frequency toggle the Audience Manager
  offers: `frequency` (POI) with its `frequency_day_part` sub-option,
  `apps_frequency` (Apps) and `web_frequency` (WebDomain). Each needs its
  dataset type in `datasets` (`422` naming the key otherwise) and the same
  feature on your account (`403`); day-part needs `frequency` and is not
  available next to an `Apps` dataset. See
  [Frequency analyses](/api/v2/audiences#frequency-analysis). The MCP
  `create_audience` and `estimate_audience_size` tools follow.

- **Create Audience can run the Frequency analysis** {{< products "API" "MCP" >}}

  [Create Audience](/api/v2/audiences#post-apiv2analysesaudiencescreate) takes
  an optional `analyses` object; `{"frequency": true}` runs the Visitation
  Frequency analysis as the audience builds, exactly as the toggle in the
  Audience Manager does, so an audience created through the API can be
  previewed and filtered by visit frequency with
  [Preview Activation](/api/v2/activations#get-apiv2analysesactivationspreview).
  Until now the API had no way to enable it, and every API-built audience was
  refused by the preview. It requires a `POI` dataset (`422` otherwise) and
  the Frequency feature on your account (`403` otherwise - ask your Account
  Manager); an unknown key under `analyses` is a `422` naming it. See
  [Frequency analysis](/api/v2/audiences#frequency-analysis). The MCP
  `create_audience` and `estimate_audience_size` tools follow.

### 2026-09-23

- **Intuizi plugin for Claude Code and Cowork** {{< products "MCP" >}}

  The MCP server can now be installed with
  `/plugin marketplace add intuizi/intuizi-claude-plugin` followed by
  `/plugin install intuizi@intuizi`, instead of adding the server URL by hand.
  The plugin carries the server declaration and a skill covering the order the
  tools are meant to be called in; authentication is the same one-click
  browser approval. It is open source at
  [github.com/intuizi/intuizi-claude-plugin](https://github.com/intuizi/intuizi-claude-plugin).
  See [Getting started](/mcp/getting-started#claude-code-and-cowork-plugin).

- **Create Audience enforces the data-scan limit** {{< products "API" "MCP" >}}

  [Create Audience](/api/v2/audiences#post-apiv2analysesaudiencescreate) now
  runs the same monthly data-scan check the console does before it creates
  anything: a company that has reached its enforced limit receives a `422`
  naming the limit and the reset date, and no audience is created or queued.
  Companies without an enforced limit are unaffected. The MCP
  `create_audience` tool follows.

- **Size estimates count as usage** {{< products "API" "MCP" >}}

  An
  [Estimate Audience Size](/api/v2/audiences#post-apiv2analysesaudiencesestimate)
  run scans the same data the create it stands in for would scan, so it now
  counts toward your company's monthly data-scan limit and is refused with the
  same `422` as a create once that limit is reached. [Usage](/api/v2/usage)
  reports it under a new sixth operation type, `estimate` (label
  `Size Estimate`), appended after `activation`; the other five keep their
  positions. Estimates run since 2026-08-24 are being recorded retroactively,
  in the month each completed. The MCP `estimate_audience_size` and
  `get_usage` tools follow.

### 2026-09-22

- **Shorter datastream errors** {{< products "API" "MCP" >}}

  The `error` of a failed datastream on
  [Get Activation](/api/v2/activations#get-apiv2analysesactivationsid),
  [List Activations](/api/v2/activations#get-apiv2analysesactivationsindex)
  and the activation webhooks no longer includes storage locations or URLs,
  and an error passed through from the query engine or cloud storage is cut to
  its first sentence, which states the reason. Processing detail that followed
  it is no longer returned. The MCP `get_activation` and `list_activations`
  tools return the same text.

### 2026-09-21

- **Origin dataset on the API** {{< products "API" "MCP" >}}

  [Create Audience](/api/v2/audiences#post-apiv2analysesaudiencescreate) and
  [Estimate Audience Size](/api/v2/audiences#post-apiv2analysesaudiencesestimate)
  accept `type: "Origin"` - people by their resolved home location, where a
  device originates. Its only filters are geographic: `location.countries` is
  required, and `location.states`, `location.cities`, `location.dmas` and
  `location.zipcodes` are optional. `signal_providers` is required as for the
  other dated types - fetch them from
  [Get Signal Providers](/api/v2/common#get-apiv2analysesreferencecommonsignal-providers)
  with `dataType=Origin`. Origin data is weekly with no day in it, so any
  dates are accepted and the window is widened to the whole Monday-to-Sunday
  weeks it touches. Coverage is limited to a few countries: fetch them from
  [Get Countries](/api/v2/common#get-apiv2analysesreferencecommoncountries)
  with `datasetType=Origin`, and a country outside that set is rejected with
  `422`.
  [Get Dataset Types](/api/v2/common#get-apiv2analysesreferencecommondataset-types)
  lists the type when it is enabled for your account, and the MCP
  `create_audience` and `estimate_audience_size` tools accept it.

### 2026-09-17

- **Reads name what an audience or cohort was built from** {{< products "API" >}}

  [Get Audience](/api/v2/audiences#get-apiv2analysesaudiencesid) returns
  `source_audience`, the seed a Lookalike Model was built from, and each
  `Cohorts` entry in `dataset` carries `cohort`, the cohort it reads.
  [Get Cohort](/api/v2/cohorts#get-apiv2analysescohortsid) returns `source`
  (`file`, `audience` or `pixel`) and `source_audience`, the audience a cohort
  was built from. Each reference is `{ "id", "name" }`, or `null` when there
  is none or the resource was deleted or belongs to another company. The list
  reads, the cohort create response and the `audience.*` / `cohort.*`
  webhooks carry the same fields.

- **Changing your password revokes every token on the account** {{< products "API" >}}

  Login tokens from [`POST /api/v2/auth/login`](/api/v2/authentication) are
  now revoked too, alongside API tokens, MCP tokens and OAuth connections, so
  log in again after a password change.

- **The wildcard scope is rejected** {{< products "API" "MCP" >}}

  `GET /oauth/authorize` answers `scope=*` with `400 invalid_scope`, and a
  refresh at `POST /oauth/token` whose `scope` is not a space-delimited string
  (for example a JSON array) or asks for `*` gets `400 invalid_scope` instead
  of a token with a different scope. A refresh that omits `scope` keeps the
  granted scope, as before.

- **A client can always revoke its own refresh token** {{< products "API" "MCP" >}}

  `POST /oauth/revoke` now revokes a refresh token even when its access token
  no longer exists.

### 2026-09-16

- **Rejected refresh tokens return `invalid_grant`** {{< products "API" "MCP" >}}

  `POST /oauth/token` now answers a refresh token that was rotated out,
  revoked, expired, or issued to another client with `400` and
  `error: invalid_grant`, as RFC 6749 specifies. It previously returned `401`
  with `invalid_request`, which OAuth clients do not treat as a reason to
  re-authorize, so a connection that lost its refresh token kept failing
  instead of asking you to reconnect. See
  [Token lifetimes](/api/v2/authentication#token-lifetimes).

### 2026-09-15

- **The 90-day audience retention rule is now scoped to MAID and IP deliveries** {{< products "API" >}}

  It exists because MAID and IP mapping keys are retained for 90 days, so it
  no longer blocks an audience outright: [audience reads](/api/v2/audiences)
  report it under a new `eligibility.notices[]` array
  (`code: audience_expired`, `blocks_identifiers: ["MAID", "IP"]`) with
  `allowed` true, and
  [Create Activation](/api/v2/activations#post-apiv2analysesactivationscreate)
  accepts EID / SCID / HEM pricing models on such an audience while rejecting
  a MAID or IP pricing model with `422`. `eligibility.reasons[]` keeps only
  the rules that block every delivery (device floor, Affinity device
  coverage). Previously any standard audience whose data window ended more
  than 90 days ago could not be activated at all, whatever the identifier.

### 2026-09-14

- **Chart opt-in on audience create is honoured** {{< products "API" >}}

  The optional [`datastreams`](/api/v2/audiences#datastream-visualizations)
  array sent to create was validated but not applied: the audience built
  without its charts and the Data Streams tab stayed empty. Opted-in streams
  now produce their pending rows and are generated as the audience builds.

- **Activation datastreams are checked against the audience** {{< products "API" >}}

  An enabled entry in [`datastreams[]`](/api/v2/activations) that applies to
  none of the audience's dataset types is now rejected with a `422` naming the
  stream, instead of being accepted and failing in the export.
  [Get Datastreams](/api/v2/common#get-apiv2analysesreferencecommondatastreams)
  items carry a new `dataset_types` field to filter on first; a lookalike
  audience counts as `cohorts`.

### 2026-09-13

- **Data stream visualizations on audience create** {{< products "API" >}}

  An audience can now generate its charts as it builds. Send the optional
  [`datastreams`](/api/v2/audiences#datastream-visualizations) array on
  create - the same `{id, visualizing_status}` shape the activation surface
  already uses. The rendered charts are viewed in the Intuizi console, on the
  audience's Data Streams tab. No endpoint returns a visualization payload or
  a PDF export.

- **New reference catalog: Get Datastream Visualizations** {{< products "API" >}}

  [Get Datastream Visualizations](/api/v2/common#get-apiv2analysesreferencecommondatastream-visualizations)
  lists the streams you may use, optionally scoped with `dataset_type` to the
  set create will accept. Distinct from Get Datastreams, which is an endpoint
  partner's delivery outputs.

### 2026-09-09

- **Cohorts from a Lookalike Model audience take a score range** {{< products "API" "MCP" >}}

  Create Cohort from a Lookalike Model audience
  (`POST /api/v2/analyses/cohorts/create` with `source` `audience`) accepts
  `score_limit` with `min_score` and `max_score`, which keeps the devices
  inside the model's score bands, best scores first, capped by
  `device_limit`. A Lookalike Model audience can now back several cohorts. MCP
  `create_cohort` advertises the same fields.

### 2026-09-02

- **Preview Cohort File works for folder sources** {{< products "API" >}}

  A `file_uri` that names a folder (no `.csv`, `.gz` or `.parquet` suffix,
  the same rule create applies) previews the header of its first data file,
  skipping Spark's `_SUCCESS` and similar markers. Previously such a preview
  failed with a 422 and the identifier column had to be typed without seeing
  the columns. See
  [Preview Cohort File](/api/v2/cohorts#post-apiv2analysescohortspreview).

- **Deleting a lookalike audience that is still modelling stops the modelling job** {{< products "API" "Console" >}}

  `POST /api/v2/analyses/audiences/delete-by-id` (and the console's delete)
  raise the same cooperative cancellation flag that `cancel-lookalike` sets,
  and the worker's progress callback honours it even after the audience row
  is gone. Previously the job ran to completion for an audience nobody could
  see. Response shapes are unchanged.

## Earlier months

- [August 2026](/developers/changelog/2026-08/index.md)
- [July 2026](/developers/changelog/2026-07/index.md)
