Archive API docs

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.

2026-08-14

  • MCP searchItems with responseFormat: "concise" now returns creator { id } on every node. It is the join key for creator-level diffs — for example differencing a campaign roster from searchCreators against that campaign’s posters — where matching on accountName is unsafe 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 (~17 ms) to the request; detailed is unchanged in both respects. See conventions and rate limits.

2026-08-09

  • Rate-limit capacity and refill now differ per plan instead of being the same for every paying plan. Read your own ceiling off RateLimit-Policy (q is the capacity, w the seconds to refill it) rather than assuming the previous flat numbers — for some plans the capacity is lower than it was. See rate limits.
  • New: Item.aiFilterReasons 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 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 documents Archive’s Model Context Protocol server — its read tools, write tools, and the conventions that hold 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.
  • itemIdsByUrl 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 — only the documentation was wrong. See 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.

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.
  • Workspaces owned by the same organization share one rate-limit bucket rather than one bucket each. See 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 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.

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.
  • 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.
  • competitorBrands and competitorBrand 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 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.
  • CompetitorBrand gained earnedMediaValue, engagementsTotal, impressions, influencersCount, postsCount, and reach, plus ownMetricsStatus — set only on the own-brand entry, distinguishing “computed, no data in window” from “could not be computed”.
  • competitorBrands and competitorBrand 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.

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, the WORKSPACE-ID workspace model, Relay-style pagination, the items filtering and search cookbook, the rate-limit layers, and the error model.