ReferenceAvo MCPTools reference

Avo MCP tools reference

Every tool except list_workspaces operates on a workspace. Pass workspaceId as a parameter; stdio clients can also set the WORKSPACE_ID environment variable.

🔒

Each tool lists the OAuth scope it requires. Write tools (workflow, save_items) require the write scope, which is requested as a separate consent step on first use.

The MCP exposes five canonical tools mapped to agent intents:

IntentToolScope
Entry point — find your workspace IDslist_workspacesread
Discover — find items by meaning or by structural filtersearchread
Understand — full details for an event, property, branch, source, etc.getread
Change — create, update, remove, or archive items on a branchsave_itemswrite
Progress — create a branch or update its descriptionworkflowwrite

Branch read flows are covered by get and search. One transitional tool — list_branches — remains available while its replacement in search(type:"branch") ships.


list_workspaces

Scope: read

List the Avo workspaces the authenticated user has access to. Call this first to discover workspace IDs before invoking any workspace-scoped tool.

Parameters

None.

Returns

One row per workspace: name, workspace ID, and the user’s role.

Examples

Discover the workspaces you can access

Prompt: “What Avo workspaces do I have access to?”

Claude calls list_workspaces with no parameters and uses the returned workspaceId to scope every other tool call in the session.


Scope: read

Find tracking plan items in one of two modes — the mode is selected automatically by which parameters you pass. Combining query with structural filters returns 400. For ID-based lookups use get.

  • Semantic search — pass query to find items by meaning across events, properties, metrics, categories, property bundles, and event variants. Uses vector similarity, not keyword matching — "user signed up" matches Account Created or Registration Completed.
  • Structured listing — omit query and pass filters to enumerate exact matches with keyset pagination.

Parameters

Shared across modes

ParameterRequiredDescription
itemTypeNoFilter by type: event (default), property, metric, category, propertyBundle, or eventVariant.
maxResultsNoSemantic mode: 1–20, default 10. Filter mode: 1–500, default 10.
workspaceIdNoWorkspace ID.

Semantic mode (pass query)

ParameterRequiredDescription
queryYesNatural language search query.

Semantic search is performed against the main branch only. The semantic index may lag slightly for very recently created or updated items.

Filter mode (omit query, pass any of the filter fields)

ParameterRequiredDescription
tagsNoFilter by tag.
categoriesNoFilter by category name.
sourcesNoFilter by source name. Does not apply to metrics.
eventNamesNoFilter by event name. With itemType: "property", returns properties on those events.
variantNamesNoFilter by event variant name.
propertiesNoWith itemType: "event", returns events referencing any of these properties.
includeVariantsNoWith itemType: "event", interleaves each event’s variants in the result set.
stakeholdersNoFilter by stakeholder.
ownersNoFilter by owner.
destinationsNoFilter by destination name.
typeNoWith itemType: "event", filter by event type.
customFieldNoFilter by custom-field name. Resolve valid names from get with type: "workspaceConfig".
piiNoFilter by PII type. Resolve valid types from get with type: "workspaceConfig".
nameMappingNoFilter by destination-name-mapping. Tagged object: { kind: "any" } (items with any mapping) or { kind: "matchesAny", names: [...], includeNoMapping?: bool } (items whose mapped name is in names; with includeNoMapping: true items without a mapping rule also pass). Omitting nameMapping means no filter on mapping.
branchIdNoBranch to enumerate on. Defaults to main.
branchNameNoAlternative to branchId.
pageTokenNoPagination token from a previous response.

Multiple values inside one array are OR’d; values across different filter keys are AND’d.

🔒

Semantic search requires Avo Intelligence Smart Search to be enabled in your workspace. Workspace admins can enable it in Workspace Settings. If you don’t have admin access, ask a workspace admin to enable it. Filter-mode listing does not require Smart Search.

Returns

Ranked results with rank, name, type, item ID, relevance percentage, and a truncated description (80 characters). Filter-mode responses include a nextPageToken when more results are available.

{
  "results": [
    {
      "rank": 1,
      "name": "Account Created",
      "itemType": "event",
      "itemId": "evt-9f2b…",
      "relevance": 0.91,
      "description": "Sent when a new account is successfully created."
    },
    {
      "rank": 2,
      "name": "Signup Started",
      "itemType": "event",
      "itemId": "evt-3c11…",
      "relevance": 0.87,
      "description": "Sent when the user opens the signup screen."
    }
  ]
}

Examples

Find events by meaning (semantic)

Prompt: “What events do we have for signup?”

Claude passes the user’s phrasing directly to query. Semantic mode returns events whose meaning matches the query, even when the exact words differ — "user signed up" will match Account Created or Registration Completed.

{
  "query": "user signed up",
  "itemType": "event",
  "maxResults": 5
}

List events using a specific property (filter)

Prompt: “Which events on iOS use the product_id property?”

Filter mode is selected by omitting query. Multiple filter keys are AND’d, so this returns only events that reference product_id and are tracked from the iOS source.

{
  "itemType": "event",
  "properties": ["product_id"],
  "sources": ["iOS"],
  "maxResults": 50
}

Common errors

  • query and structural filters combined — returns 400. Choose one mode.
  • Smart Search not enabled in the workspace — semantic mode fails; fall back to filter mode or get.
  • Workspace access denied.

get

Scope: read

Get item details for any of four type families:

  • Tracking-plan itemsevent, property, metric, category, propertyBundle, eventVariant. Look up by id or exact name. For events, includePropertyDetails: true returns each property’s type, constraints, and allowed values inline.
  • Workspace metadatasource, destination, groupType. Pass id or name for one item; omit both to enumerate the workspace list.
  • Workspace configworkspaceConfig. Naming/casing rules, custom-field definitions, and the PII type list. Custom-field and PII-type names plug straight into search’s customField and pii filters.
  • Branchesbranch. Identify with branchId or branchName. Use include to pick content: "overview" (branch metadata + baseline status), "changes" (diff vs. main, like the web branch screen), "code_snippets" (per-source generated code; requires sourceId). include defaults to ["overview"].

Defaults to the main branch when no branch is specified.

Parameters

ParameterRequiredDescription
typeYesItem type. One of: event, property, metric, category, propertyBundle, source, destination, groupType, eventVariant, branch, workspaceConfig.
idVaries by typeThe item’s unique ID. Required for event, property, metric, category, propertyBundle, eventVariant unless name is provided. Optional for source/destination/groupType (omit both id and name to enumerate). Optional for branch (defaults to the active branch context if omitted). Not used by workspaceConfig.
nameVaries by typeExact name match. Alternative to id for most types. May return multiple matches for ambiguous names (especially properties) — use search for fuzzy lookup.
variantIdFor eventVariantThe variant ID. Combined with id (the base event ID).
includeFor branchArray of branch facets to return: overview, changes, code_snippets. Defaults to ["overview"]. Combine changes and code_snippets for an implementer-ready picture of the branch.
sourceIdWhen include contains code_snippetsSource ID to scope the code snippets to.
branchIdNoBranch to look up on. Defaults to main. branchId takes precedence over branchName.
branchNameNoAlternative to branchId.
includePropertyDetailsNoEvents only. When true, includes full property definitions (type, constraints, allowed values). Defaults to false, which returns only property ID + name references.
includeArchivedNoWhen true (default), includes archived items in results. When false, only active items.
workspaceIdNoWorkspace ID

Returns

Full details for the item, shaped per item type.

  • type: "event" \| "property" \| "metric" \| "category" \| "propertyBundle" \| "eventVariant" — the item’s full definition.
  • type: "source" \| "destination" \| "groupType" — a single entity when id/name is provided, or a workspace-level list when both are omitted.
  • type: "branch" — branch facets requested via include. overview returns resolved emails for the creator, reviewers, and collaborators, branch status, impacted source IDs, and description. changes returns the structured diff (new, modified, and deleted events with their properties and descriptions). code_snippets returns per-event code diffs for the source named in sourceId — exact unified diffs for Avo Codegen sources and illustrative pseudocode for manually-instrumented sources.
  • type: "workspaceConfig" — the workspace’s event/property naming conventions and casing rules, plus custom field definitions and the list of recognized PII types. Use this before proposing new events or properties so names match the workspace’s audit rules.

Examples

Look up an event by exact name

Prompt: “How is the Account Created event defined?”

Claude calls get with the exact name and includePropertyDetails: true so the response includes each attached property’s type, constraints, and allowed values. Useful when the agent already knows the canonical name and wants the full schema in one call.

{
  "type": "event",
  "name": "Account Created",
  "includePropertyDetails": true
}

Read what changed on a branch

Prompt: “What’s on the checkout-v2 branch — and can you show me the iOS code diff?”

Claude calls get with type: "branch" and combines changes and code_snippets in include. sourceId scopes the diff to a single source.

{
  "type": "branch",
  "branchName": "checkout-v2",
  "include": ["changes", "code_snippets"],
  "sourceId": "src-ios"
}

Common errors

  • Item not found.
  • Ambiguous name (returns multiple matches — narrow by ID).
  • sourceId missing when include contains code_snippets.
  • Workspace access denied.

save_items

Scope: write

🚧

Write access is in general beta — enabled for every workspace, no need to request access. Email support@avo.app if you hit anything unexpected.

Batch create, update, remove, and archive events, properties, event variants, property bundles, and metrics on a branch. A single call can mix item types and operations, and can cross-reference new items via temporary IDs.

Parameters

Top-level

ParameterRequiredDescription
branchIdYesThe branch to write to. Get it from workflow (action: "create_branch").
itemsYesArray of items to apply. Each item is typed by its type field and has an op (default create).
workspaceIdNoWorkspace ID

The request is capped at 100 items per call.

Item shape

Every item shares these fields:

FieldTypeNotes
op"create" | "update" | "remove" | "archive"Defaults to "create". Not every op applies to every type — see “Supported ops” below. For events, "archive" is the canonical archive op and "remove" is accepted as a legacy alias that behaves identically. For properties and property bundles, "remove" is the archive op (no "archive" variant).
type"event" | "property" | "event_variant" | "property_bundle" | "metric"Required.
namestringRequired on create for events, properties, property bundles, and metrics. Cosmetic on event_variant items and on update/remove/archive of other types.
tempIdstringCreate only. Declares a temporary handle (e.g. "prop1"). Reference it elsewhere in the same call as "$tmp:prop1". The server allocates a real ID and resolves all $tmp: references before writing.
eventIdstringRequired on update / archive (or legacy remove) of events.
propertyIdstringRequired on update / remove of properties.
propertyBundleIdstringRequired on update / remove of property bundles.
metricIdstringRequired on update / archive of metrics.
baseEventIdstringRequired for event_variant items — the parent event’s ID.
variantIdstringRequired on update of event_variant. On create, provide either variantId directly or a tempId on the same item.
nameSuffixstringRequired on create of event_variant — suffix appended to the parent event name (e.g. buy_now produces click / buy_now).
descriptionstringCreate-only. Event / property / bundle / metric description.

Supported ops by type:

Typecreateupdateremovearchive
event✅ (legacy alias for archive)✅ (archives the event)
property✅ (archives the property + cascades references)
event_variant❌ (see “Not yet implemented”)
property_bundle✅ (archives the bundle)
metric

Create-event fields:

FieldNotes
propertiesArray of property IDs (or $tmp: refs) to attach.
propertyBundlesArray of property bundle IDs (or $tmp: refs) to attach to the event.
sourcesArray of source IDs to include the event in. Find source IDs with get (type: "source" with id/name omitted to enumerate).
tagsArray of literal tag-name strings to apply to the event.

Create-property fields:

FieldNotes
propertyTypestring, int, long, float, bool, object, any (aliases like integer, boolean, double accepted).
sendAsevent, user, or system.
tagsArray of literal tag-name strings to apply to the property.
eventConfigs(optional) Per-event/per-source property settings on a fresh property. On create, only events: { kind: "allEvents" } entries are accepted — per-event-scoped entries are rejected because the property isn’t attached to any event yet. See “Per-event property settings (eventConfigs)” below.

Create-event_variant fields:

FieldNotes
attachPropertiesArray of property IDs (or $tmp: refs) to attach to the variant.
overridesComponent-level overrides. Each entry: { propertyId, pinned } or { propertyId, allowed }. pinned and allowed are mutually exclusive per override.
bundleOverridesBundle IDs to attach to the variant as property bundles.

Create-property_bundle fields:

FieldNotes
addPropertiesProperty IDs (or $tmp: refs) to include in the bundle.
attachToEventsEvent IDs (or $tmp: refs) the new bundle should be attached to.

Create-metric fields:

FieldNotes
metricTypeRequired. One of Funnel, EventSegmentation, Proportion, Retention, CustomEvent, Cohort. Immutable after create — archive and recreate to change.
itemsRequired for non-cohort metrics. Array of metric items referencing events by eventId (or $tmp: ref), with optional baseEventId for event variants.
cohortConditionsRequired for Cohort metrics. Array of conditions referencing events by eventId (or $tmp: ref) and optional propertyId.

Update-event fields: (require eventId)

FieldNotes
set.nameRename the event. Renaming to the same name is a no-op; renaming to a name already held by another live event is rejected.
set.descriptionNew event description.
addProperties / removePropertiesProperty IDs (or $tmp: refs) to associate / disassociate.
addPropertyBundles / removePropertyBundlesProperty bundle IDs (or $tmp: refs) to attach / detach.
addSources / removeSourcesSource IDs to include / exclude.
addTags / removeTagsTop-level on the item, not inside set. Tag-name strings to apply or remove.

Update-event_variant fields: (require baseEventId + variantId)

FieldNotes
set.nameSuffixNew variant suffix.
set.descriptionNew variant description.
attachProperties / removePropertiesProperty IDs to attach / detach from this variant.
addComponentOverridesOverride specs to add or replace. Same shape as create overrides.
removeComponentOverridesProperty IDs whose overrides should be cleared.

Update-property fields: (require propertyId)

FieldNotes
set.nameRename the property. Renaming to the same name is a no-op; renaming to a name already held by another live property is rejected.
set.descriptionNew property description.
set.propertyTypeNew type. Same value set as create: string, int, long, float, bool, object, any (aliases like integer, boolean, double accepted).
addAllowedValuesTop-level on the item, not inside set. String values to add to a string-typed property’s allowed list.
removeAllowedValuesTop-level on the item, not inside set. Values not in the current list are silently no-ops.
addTags / removeTagsTop-level on the item, not inside set. Tag-name strings to apply or remove.
isListTop-level on the item, not inside set. Boolean — switches the property between scalar (false) and list (true). Property-only.
eventConfigsTop-level on the item. Per-event/per-source property settings — change presence, pin a value, or restrict allowed values per event. See “Per-event property settings (eventConfigs)” below.

Update-property_bundle fields: (require propertyBundleId)

FieldNotes
set.nameRename the bundle.
set.descriptionNew bundle description.
addProperties / removePropertiesProperty IDs (or $tmp: refs) to add / remove from the bundle. Bundle-to-event attachment is managed from the event side via addPropertyBundles / removePropertyBundles on event-update items.

Update-metric fields: (require metricId)

FieldNotes
setNameRename the metric.
setDescriptionNew metric description.
addItems / removeItemsFor non-cohort metrics, add or remove metric items.
addCohortConditions / updateCohortConditions / removeCohortConditionsFor Cohort metrics, manage the cohort condition list.

Archive-event: (require eventId)

{ op: "archive", type: "event", eventId: "..." } archives the event on the branch. { op: "remove", type: "event", eventId: "..." } is accepted as a legacy alias and behaves identically.

Remove-property: (require propertyId)

{ op: "remove", type: "property", propertyId: "..." } archives the property on the branch and cascades removal references on every event that uses it, mirroring the Avo UI. Properties use op: "remove" for archive — there is no separate op: "archive" for properties. The action is destructive but reversible from the Avo app. If you only have the property name, look up the ID first with get or search so that any name-conflict ambiguity is surfaced before the mutation runs.

Remove-property_bundle: (require propertyBundleId)

{ op: "remove", type: "property_bundle", propertyBundleId: "..." } archives the bundle on the branch. Bundles use op: "remove" for archive — there is no separate op: "archive" for bundles.

Archive-metric: (require metricId)

{ op: "archive", type: "metric", metricId: "..." } archives the metric on the branch.

Per-event property settings (eventConfigs)

eventConfigs is a top-level array on an update-property item (and, restricted to events: { kind: "allEvents" }, on a create-property item). Each entry adjusts how the property behaves on a specific event or across all events:

  • setPresence — change presence to alwaysSent, sometimesSent, or neverSent. Can be scoped per source.
  • setPinnedValue — pin a value for the property. With events: { kind: "onEvent" } pins per-event; with events: { kind: "allEvents" } pins property-wide.
  • restrictAllowedValues — change the property’s allowed value list for an event. Carries a valuesChange delta: addValues (non-empty), removeValues, or clear (no payload).

eventConfigs entries reference pre-existing events — a same-batch create-event item isn’t visible to eventConfigs yet, so create the event in an earlier call (or the same batch, ordered before the property update that references it).

🚧

Not yet implemented. The following return a NotYetImplemented error from the server:

  • op: "remove" on event_variant items
  • set.sendAs on op: "update" of property items — sendAs is immutable after create

Everything else works today: create / update events, properties, event variants, property bundles, metrics; archive events, properties, bundles, metrics; rename events and properties via set.name; toggle a property between scalar and list via isList; apply or remove tags via addTags / removeTags; per-event property settings via eventConfigs.

Temporary IDs (tempId / $tmp:)

To reference a newly-created item from another item in the same call, declare a tempId on the create item and reference it elsewhere as "$tmp:<name>":

  • tempId is create-only — setting it on an update, remove, or archive returns an error.
  • tempId names must be unique within a single save_items call.
  • $tmp: references are resolved in these array fields: properties, addProperties, removeProperties, attachProperties, propertyBundles, addPropertyBundles, removePropertyBundles, attachToEvents, addSources, removeSources, bundleOverrides; inside overrides[].propertyId / addComponentOverrides[].propertyId; and within nested metric fields (items[].metricId / eventId / baseEventId, cohortConditions[].eventId / propertyId). Source and destination IDs must be real IDs — save_items does not create those entity types.
  • If a $tmp: ref names a tempId that wasn’t declared on any item, the server returns a validation error.

Returns

A structured result with:

  • createdEntities, updatedEntities, removedEntities, archivedEntities — each entry has name, entityId, and entityType (event, property, event_variant, property_bundle, or metric).
  • errors — per-item validation or audit errors, each with the item index, name, and a message.
  • warnings — non-fatal notices, same shape as errors.
  • success — overall boolean.
{
  "success": true,
  "createdEntities": [
    { "name": "Checkout Method", "entityId": "prop-9d44…", "entityType": "property" }
  ],
  "updatedEntities": [
    { "name": "Checkout Completed", "entityId": "evt-3f01…", "entityType": "event" }
  ],
  "removedEntities": [],
  "errors": [],
  "warnings": []
}

Examples

Create a new event with a new property in one call

Prompt: “Add a Checkout Completed event with a Checkout Method property for Web and iOS.”

Claude declares a tempId on the new property so the new event can attach it before the server has allocated a real ID. The server resolves the $tmp: reference, allocates the real propertyId, attaches the property to the event, and includes the event in both sources — all atomically.

{
  "branchId": "br-abc123",
  "items": [
    {
      "op": "create",
      "type": "property",
      "tempId": "checkout_method",
      "name": "Checkout Method",
      "propertyType": "string",
      "sendAs": "event",
      "description": "How the user completed checkout"
    },
    {
      "op": "create",
      "type": "event",
      "name": "Checkout Completed",
      "description": "Fired when the user finishes checkout",
      "properties": ["$tmp:checkout_method"],
      "sources": ["src-web", "src-ios"]
    }
  ]
}

Define a checkout funnel metric

Prompt: “Add a funnel metric on this branch that tracks the share of users who start checkout and complete it.”

Claude creates a Funnel metric whose items reference two existing events in order. The same call could chain in new events with $tmp: references if the funnel needed events that don’t exist yet.

{
  "branchId": "br-abc123",
  "items": [
    {
      "op": "create",
      "type": "metric",
      "name": "Checkout Funnel",
      "description": "Share of users who start checkout and complete it.",
      "metricType": "Funnel",
      "items": [
        { "eventId": "evt-checkout-started" },
        { "eventId": "evt-checkout-completed" }
      ]
    }
  ]
}

Common errors

  • Missing write scope — the client must re-authorize with write.
  • branchId is required / items is required — malformed request.
  • tempId is only valid on create items — don’t set tempId on update or remove.
  • Duplicate tempId "<name>" — each tempId must be unique across items in the batch.
  • Unknown $tmp: reference — a $tmp: ref names a tempId that wasn’t declared.
  • <idField> is required for <op> <entity> items — missing eventId / propertyId / baseEventId / variantId / propertyBundleId / metricId.
  • too many items (got N, max 100) — batch is over the 100-item cap.
  • NotYetImplemented — one of the unsupported operations above.
  • Per-item audit-pipeline validation failures (e.g. illegal name, duplicate property, etc.) — returned inside the errors array rather than failing the whole call.

workflow

Scope: write

🚧

Write access is in general beta — enabled for every workspace, no need to request access. Email support@avo.app if you hit anything unexpected.

Branch-lifecycle write operations. Currently supports two actions:

  • create_branch — open a new branch.
  • update_branch_description — set the description on an existing open branch.
💡

A branch is a draft workspace for tracking-plan changes, analogous to a git branch. All write operations via the MCP happen on a branch — save_items requires a branchId that exists. The MCP never merges to main; open the branch in the Avo app to review and merge.

Parameters

ParameterRequiredDescription
actionYesThe workflow action. One of: create_branch, update_branch_description.
branchNameFor create_branch; alternative to branchId for update_branch_descriptionName for the new branch (create_branch), or the existing branch’s name (update_branch_description).
branchIdAlternative to branchName for update_branch_descriptionID of the existing branch to update. Provide exactly one of branchId or branchName.
descriptionFor update_branch_descriptionThe new description text.
workspaceIdNoWorkspace ID

Returns

For create_branch: the new branch’s branchId, branchName, and a branchUrl that opens it in the Avo web app. For update_branch_description: confirmation with the resolved branchId and the updated description.

Examples

Create a branch for a new feature

Prompt: “Start an Avo branch for the new checkout flow we’re shipping next sprint.”

Claude calls workflow with action: "create_branch" and a descriptive branchName. The returned branchId is required for the follow-up save_items calls that write the new events and properties.

{
  "action": "create_branch",
  "branchName": "add-checkout-tracking"
}

Update a branch’s description

Prompt: “Update the description on the add-checkout-tracking branch to mention that we’re now also tracking abandonment.”

Claude looks up the branch by name (no separate branchId lookup needed for this action) and replaces the description in one call.

{
  "action": "update_branch_description",
  "branchName": "add-checkout-tracking",
  "description": "Adds the Checkout Completed and Checkout Abandoned events with the Checkout Method property."
}

Common errors

  • Missing write scope — re-authorize with write.
  • Workspace access denied.
  • Unsupported action value.
  • Both branchId and branchName provided — update_branch_description requires exactly one.

list_branches

Scope: read

🚧

Transitional. This tool stays available while branch enumeration is being folded into search with type: "branch". Until that ships, use list_branches to enumerate branches.

Browse branches in a workspace with filtering and pagination. Results are paginated newest-first.

Parameters

ParameterRequiredDescription
workspaceIdNoWorkspace ID
branchStatusesNoFilter by status. Valid values: Draft, ReadyForReview, ChangesRequested, Approved, Merged, Closed, Open. Defaults to open/active branches only.
pageSizeNoResults per page (1–50, default 25)
pageTokenNoPagination token from a previous response
branchNameNoSubstring match on branch name (case-insensitive)
creatorEmailNoFilter by creator email
creatorUserIdNoFilter by creator user ID
reviewerEmailNoFilter by reviewer email
reviewerUserIdNoFilter by reviewer user ID
collaboratorEmailNoFilter by collaborator email
collaboratorUserIdNoFilter by collaborator user ID
createdAfterNoISO 8601 date — only branches created after
createdBeforeNoISO 8601 date — only branches created before
impactedSourceIdNoFilter to branches affecting a specific source

By default Merged and Closed branches are excluded. Pass branchStatuses: ["Merged"] (or any other value) to include them.

💡

To find “my branches,” pass your own email as creatorEmail or reviewerEmail. The tool does not auto-inject your identity into the filter.

Returns

Compact per-branch summary — name, status, ID, creator email — plus a nextPageToken when more results are available. Call get with type: "branch" and include: ["overview"] for full resolved data.

Examples

Find branches I’m reviewing

Prompt: “What branches am I assigned to review?”

Claude passes the user’s email as reviewerEmail and filters status to ReadyForReview. The tool does not auto-inject the caller’s identity, so the email has to be supplied explicitly.

{
  "reviewerEmail": "thora@avo.sh",
  "branchStatuses": ["ReadyForReview"]
}

Common errors

  • Workspace access denied.
  • Invalid pageSize (outside 1–50).
  • Invalid date format on createdAfter / createdBefore.