# Changelog

Changes to the Archive API and to these guides, newest first.

## About this changelog

This page records partner-visible changes to the `/api/v2` surface: schema additions and removals, authentication or header changes, rate-limit behavior, and error-shape changes. Add an entry in any pull request that changes the GraphQL schema or guide-visible behavior, dated by its merge date, with one bullet per change.

## Stability and versioning

Everything this documentation describes as generally available changes **additively only**. New fields, arguments, types, enum members, and MCP tools may appear at any time; existing ones are not renamed, removed, or changed in meaning. The same rule covers MCP tool names and input schemas, and the [webhook delivery envelope](/api/v2/docs/guides/webhooks#the-delivery-request) — new keys may be added, existing keys keep their shape.

Build for that: select only the fields you use, ignore unknown keys in JSON payloads, and treat unrecognized enum values as “other” rather than an error. A change that would break a correctly built integration ships as a **new URL version** (an `/api/v3`), never in place on `/api/v2`.

Coverage began at different times: the GraphQL schema has been additive-only since launch, while MCP tools joined the contract when the tool surface went generally available on **2026-08-14**. MCP-only breaking changes from before that date — such as the 2026-07-25 argument-casing migration — were part of the pre-GA shakedown and are recorded below as **Breaking (MCP only)** entries; none can recur now that the tools are GA.

The one exception is [alpha features](/api/v2/docs/guides/alpha-features), which are opt-in precisely because they carry no stability contract. Everything else that is partner-visible — schema, behavior, limits, error shapes — lands as a dated entry below when it changes.

## 2026-08-21

- Every docs page now links the [terms of service](https://go.archive.ai/terms-of-service) and [privacy policy](https://go.archive.ai/privacy-policy) in a footer; previously they were reachable only from the MCP security page.
- This page now states the `/api/v2` [stability contract](#stability-and-versioning) explicitly: the GA surface changes additively only, and a breaking change would ship as a new URL version. The GraphQL schema has operated under this rule since launch; MCP tools since their GA on 2026-08-14. It is now written down where partners can cite it.
- New [Webhooks guide](/api/v2/docs/guides/webhooks): triggering model, the delivery request and signature verification, retry and auto-disable behavior, testing and monitoring, and per-plan limits. The webhook reference pages are unchanged; this adds the prose walkthrough.

## 2026-08-14

- MCP `searchItems` with `responseFormat: "concise"` now returns `creator { id }` on every node. This is the join key for creator-level comparisons, such as matching a campaign roster from `searchCreators` against that campaign’s posters; matching on `accountName` is unsafe there because a workspace can hold two creator records that share a handle. The added relation raises a concise `searchItems` call’s weighted cost by 8 (a 20-row page goes from 55 to 63) and adds one batched creator lookup (about 17 ms) per request. `detailed` responses are unchanged in both respects. See [conventions](/api/v2/docs/mcp/conventions) and [rate limits](/api/v2/docs/guides/rate-limits).

## 2026-08-09

- Rate-limit capacity and refill rate now vary by plan instead of being the same for every paying plan. Read your ceiling from the `RateLimit-Policy` header (`q` is the capacity, `w` the seconds to refill it) rather than assuming the previous flat numbers; for some plans the capacity is now lower. See [rate limits](/api/v2/docs/guides/rate-limits).
- Rate-limit buckets are per-workspace again. A workspace owned by an organization takes its capacity and refill rate from the organization’s plan but keeps its own balance, so one workspace’s traffic no longer drains its sibling workspaces’ quota. This reverses the organization-pooled buckets introduced on 2026-08-01. See [rate limits](/api/v2/docs/guides/rate-limits).
- **New:** [`Item.aiFilterReasons`](/api/v2/docs/types/item) returns the explanation an AI Filter produced for each AI-generated custom-attribute value on an item. Every entry pairs to a value: a `key` is only returned when the item carries a value for it in `customAttributes`. `reason` is `null` when the run recorded no explanation and `""` when the model produced an empty one. The list is empty, never null, when an item has none.
- **New:** [`CustomAttributeSchema.aiGenerated`](/api/v2/docs/types/custom-attribute-schema) marks which attribute keys are generated by an AI Filter, so you can discover which keys carry reasons before requesting them.

## 2026-08-06

- **New:** the [MCP section](/api/v2/docs/mcp) documents Archive’s Model Context Protocol server: its [read tools](/api/v2/docs/mcp/read-tools), [write tools](/api/v2/docs/mcp/write-tools), and the [conventions](/api/v2/docs/mcp/conventions) that apply across every tool. Each tool wraps exactly one public root field, and every operation’s reference page now links to the tool that wraps it.
- The seven list fields that return a plain list rather than a connection now return at most 1000 rows. The cap is silent; there is no cursor to continue from. See [pagination](/api/v2/docs/guides/pagination).
- [`itemIdsByUrl`](/api/v2/docs/queries/item-ids-by-url) accepts any public HTTP(S) URL. It returns `INVALID_URL` only for a malformed URL, a non-HTTP scheme, or a private/reserved host. A well-formed public URL with no matching item now returns `NOT_FOUND` rather than `INVALID_URL`.
- Clarified that a Social Profile View’s and a workspace Creator View’s `filters` blob is stored and echoed back but not applied when reading through `socialProfiles(presetId:)` or `creators(presetId:)`. This is long-standing behavior, not a change; the documentation was previously wrong. See [filtering](/api/v2/docs/guides/filtering).

## 2026-08-02

- MCP requests now charge and refund the same pooled organization bucket as `/api/v2`, so routing load through `/api/v2/mcp` no longer multiplies an organization’s capacity. See [rate limits](/api/v2/docs/guides/rate-limits).

## 2026-08-01

- `POST /api/v2` accepts `variables` as a JSON-encoded string as well as a JSON object, and honors `operationName`, so a document that defines several operations is usable. A string `variables` previously returned a non-JSON error page.
- An unhandled resolver error now returns a coded GraphQL error envelope instead of a non-JSON error page. See [errors](/api/v2/docs/guides/errors).
- Workspaces owned by the same organization share one rate-limit bucket rather than one bucket each. See [rate limits](/api/v2/docs/guides/rate-limits).
- **Breaking (MCP only):** `tools/list` now requires credentials and answers an unauthenticated call with the same RFC 9728 discovery challenge as `initialize`.
- MCP tool arguments now enforce the `minimum`, `maximum`, and `minLength` bounds that `tools/list` advertises for them.
- Revoking an MCP connection now revokes its whole refresh-token rotation lineage, so a superseded credential can no longer mint access tokens.
- `uploadItemFromUrl` rejects URLs whose host is a private or reserved address, or that carry no host at all.

## 2026-07-31

- The weighted cost model is now enforced: a request that exhausts the bucket is rejected with HTTP 429, a `Retry-After` header, and a `RATE_LIMIT_EXCEEDED` error. It previously ran in shadow mode and only reported cost in headers. See [rate limits](/api/v2/docs/guides/rate-limits).

## 2026-07-30

- `after` cursors are bound to the connection that issued them and shape-checked per entity, so a cursor borrowed from another connection fails with the coded `Invalid cursor` error rather than an internal error. See [pagination](/api/v2/docs/guides/pagination).
- The payload-heavy MCP read tools accept `responseFormat: "concise" | "detailed"`. `detailed` is the default and its shape is unchanged.

## 2026-07-29

- A query canceled by the database statement timeout now returns a GraphQL error envelope with the stable `QUERY_TIMEOUT` code instead of a non-JSON error page. See [errors](/api/v2/docs/guides/errors).
- [`competitorBrands`](/api/v2/docs/queries/competitor-brands) and [`competitorBrand`](/api/v2/docs/queries/competitor-brand) keep returning roster data when aggregate metrics are temporarily unavailable, and report the outage as a `SERVICE_UNAVAILABLE` error alongside the data. Match on `extensions.code` to decide whether to retry; `ownMetricsStatus: UNAVAILABLE` alone no longer implies a retry will help.
- MCP tool responses were trimmed to the fields each tool needs for its stated purpose; 20 tools now return fewer fields.
- MCP honors the `MCP-Protocol-Version` request header.

## 2026-07-28

- A superseded MCP refresh token is now revoked when its successor is used. Superseded refresh tokens previously stayed valid indefinitely. The OAuth discovery document also advertises the `revocation_endpoint`, so clients can log out cleanly.

## 2026-07-27

- `refetchEngagementBulk` is available to every API-enabled workspace. The separate engagement-refresh feature gate is gone, and its `userErrors` no longer report “feature not enabled”. The mutation is still credit-gated.
- MCP answers the `ping` method with the protocol’s empty result instead of `-32601 Method not found`.

## 2026-07-26

- [`competitorBrands`](/api/v2/docs/queries/competitor-brands) now returns your own brand as one additional pinned node on the first page, named `You` and flagged by the new `isOwnBrand` field, so you can compute self-vs-competitor Share of Voice. `totalCount` still counts tracked competitors only, so page one returns one more edge than it reports. See [pagination](/api/v2/docs/guides/pagination).
- [`CompetitorBrand`](/api/v2/docs/types/competitor-brand) gained `earnedMediaValue`, `engagementsTotal`, `impressions`, `influencersCount`, `postsCount`, and `reach`, plus `ownMetricsStatus`, which is set only on the own-brand entry and distinguishes “computed, no data in window” from “could not be computed”.
- `competitorBrands` and [`competitorBrand`](/api/v2/docs/queries/competitor-brand) accept `period` (`WEEK`/`MONTH`, default `MONTH`) and `date` to select the metric window. `competitorBrand` also resolves the own-brand entry by its stable ID.

## 2026-07-25

- Malformed or foreign pagination cursors now fail with a coded `Invalid cursor` error instead of a generic internal error, across every cursor-paginated connection.
- **Breaking (MCP only):** every MCP tool argument is now camelCase (`itemId`, `presetId`, `viewIds`), matching the GraphQL field names one-to-one. Stored keys inside the opaque saved-view `filters` blob stay snake\_case; clone them verbatim. The `/api/v2` GraphQL surface is unchanged.

## 2026-07-24

- MCP responses now carry the same IETF `RateLimit` and `RateLimit-Policy` headers as `/api/v2`. See [rate limits](/api/v2/docs/guides/rate-limits).

## 2026-07-23

- Recalibrated the base rate-limit plan to a capacity of 15000 with a refill of 250 per second.
- Published the Archive API documentation site: task-oriented guides plus a schema-driven reference for every query, mutation, and type.
- Documented the generally available surface: bearer-token [authentication](/api/v2/docs/guides/authentication), the `WORKSPACE-ID` [workspace model](/api/v2/docs/guides/workspaces), Relay-style [pagination](/api/v2/docs/guides/pagination), the `items` [filtering and search](/api/v2/docs/guides/filtering) guide, the [rate-limit](/api/v2/docs/guides/rate-limits) layers, and the [error model](/api/v2/docs/guides/errors).
