- Brand
- Archive
- Category
- Marketing
- Primary Subcategory
- Influencer & Creator Discovery
Integration details
Description
Archive helps teams search workspace social content and creators, inspect campaigns, saved views, collections, operations, and webhooks, and manage those workspace records through ChatGPT.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Influencer & Creator Discovery
- Secondary Subcategories
- None listed
- Brand
- Archive
- Access
- Account required
- First tracked
- 2026-09-13
- Tool count
- 77
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
Your score is coming
ChatGPT now suggests Plugins on its own when they match a user's request.Your Plugin Discovery Score measures how often yours appears, and it will show here as soon as it’s ready.
What discovery looks like

Get alerts for Archive
Get updates when Archive’s Discoverability Score or category rank changes.
Competing in ChatGPT Influencer & Creator Discovery
View Category77 tools agents can invoke
PURPOSE: Add an item to one or more Collections in the current workspace. A Collection is a workspace-scoped tag set (a saved multi-select tag) applied to items; adding an item to a Collection tags it, so the item then appears when that Collection is used as a filter. INPUT: - itemId (required string): the Archive item id to tag. - collectionIds (array of strings, default [], at most 50): Collection ids to add the item to. - collectionNames (array of strings, default [], at most 50): Collection names to add the item to, matched case-sensitively within the workspace, as sent or else trimmed of surrounding whitespace and invisible characters and NFC-normalized. - autoCreate (boolean, default false): when true, a name in `collectionNames` that does not match an existing Collection creates a new Collection; when false, unmatched names are dropped and, if NO collection resolves at all, the call returns a "No valid collections found" userError. You MUST provide at least one of `collectionIds` or `collectionNames`. Providing neither returns a userErrors entry ("Provide 'collectionIds' or 'collectionNames'") and makes no change. RESOLVING IDS vs NAMES: prefer ids. Resolve Collection ids with getCollections first, then pass them as `collectionIds`. Use the ids returned by getCollections for THIS workspace: several id forms are accepted depending on how the workspace stores Collections. An id from another workspace, or one this workspace cannot write through this API, rejects the WHOLE call (all-or-nothing) with a userErrors entry naming the offending id under `collectionIds`. An id that exists in the workspace but is not writable here reports "exists in this workspace but is not writable through this API" — re-resolve via getCollections and retry with the id it returns. AUTO_CREATE: use `autoCreate: true` only when creating a Collection is intended. It creates the new Collection in this workspace's own Collection storage, under the name trimmed and NFC-normalized. A name that is blank or only invisible characters, longer than 255 characters, or holding control or bidirectional text characters is rejected with a userError on ["collectionNames"], and nothing is created. Resolve names via a read tool first when you mean to reference an existing Collection — a typo with `autoCreate: true` silently creates an unwanted Collection. OUTPUT: { item: { id, customAttributes } | null, userErrors: [{ field, message }] }. `item` is the item as stored after the write. In workspaces whose Collections use the older storage, `item.customAttributes.collections` does NOT reflect Collection membership and is returned unchanged — use getCollection(id:).itemCount to confirm the write. In preset-backed workspaces that array holds the item's Collections after the write, as option ids — not the Collection `id`s getCollections returns; match them against each Collection's `customAttributeOptionId` from getCollections. `userErrors[].field` is an array of path segments (e.g. ["collectionIds"]). VERIFY AFTER WRITE: PRIMARY (works in every workspace): getCollection(id: "<collection-id>") — its `itemCount` reflects the change immediately. Default to this check. SECONDARY (works in every workspace): searchItems(filter: { collectionsIds: ["<collection-id>"] }) with a Collection id from getCollections, and check the item is present. Search results lag a write by up to about a minute, so this is confirmation, not the immediate check. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
addItemToCollections
PURPOSE: Assign labels to creators in the current workspace. Labels are set membership keyed by name: assigning a label a creator already carries is a success no-op, so repeating the call is safe. WHICH TOOL: up to 40 creators → this tool (synchronous). More → bulkAddLabelsToCreators (background operation, up to 1000 per call, a flat 250 points). INPUT: - creatorIds (required array of strings, 1-40): creator ids from searchCreators or getCreator. If any id does not resolve in this workspace the WHOLE call is rejected (all-or-nothing, nothing written) with a userError on ["creatorIds"] naming it. - labelNames (required array of strings, 1-50, each at most 100 characters): label names; matching ignores case and surrounding whitespace. MINT ON ASSIGN: Assigning a label that does not exist yet creates it. Check getLabels first when you mean an existing label; a typo adds a new one. A label with `deleting: true` is being removed; do not assign it, and do not recreate it until it disappears from getLabels. OUTPUT: { creators: [{ id, customAttributes }], userErrors: [{ field, message }] }. `creators` is empty when userErrors is non-empty. A label being deleted is a userError on ["labelNames"]; a workspace with no user to attribute the write to is one on ["base"]. Lock contention with another write is an error to retry, not a userError. COST: 50 rate-limit points for the first creator plus 100 for each additional one. A call costing more than the workspace's rate-limit capacity is a userError on ["creatorIds"] naming the largest call that fits; nothing is written or charged. LABEL WRITE LIMIT: a workspace labels at most 40 creators at once, then one creator every 2 seconds, shared by every caller. Past it the call is an error "Label write limit exceeded: … Retry after N seconds." — wait N seconds, then retry. VERIFY AFTER WRITE: call getCreator(id:) and read the `labels` key of the returned `customAttributes` JSON object — it is a path inside the JSON value, never a selection set; call getLabels as well when a name may have been newly created. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
addLabelsToCreators
PURPOSE: Assign labels to many creators in the current workspace as a background operation. Labels are set membership keyed by name: a creator already carrying a label is left as is, so repeating the call is safe. WHICH TOOL: up to 40 creators → addLabelsToCreators (synchronous, returns the creators). More → this tool, up to 1000 creators per call; split larger sets into several calls. INPUT: - creatorIds (required array of strings, 1-1000): creator ids from searchCreators or getCreator. An id that does not resolve in this workspace is skipped and returned in skippedCreatorIds; the rest are scheduled. - labelNames (required array of strings, 1-50, each at most 100 characters): label names; matching ignores case and surrounding whitespace. MINT ON ASSIGN: a name that matches no label creates it. Check getLabels first when you mean an existing label; a typo adds a new one. Do not assign a label with `deleting: true`. COST: a flat 250 rate-limit points per call, whatever the creator count. IN FLIGHT: at most 2 creator label bulk operations — including bulk edits made in the Archive app — run per workspace at once; a third is a userError on ["base"] naming the running ones. Wait for one to finish, then retry. OUTPUT: { scheduled, operationId, acceptedCount, skippedCreatorIds, userErrors: [{ field, message }] }. `scheduled` is false with a null operationId when userErrors is non-empty or no id resolved. A label being deleted is a userError on ["labelNames"]. VERIFY AFTER WRITE: poll getOperation(id: operationId) until status is COMPLETED, PARTIAL or FAILED; read per-creator failures with getOperationRecords; then spot-check getCreator(id:) and read the `labels` key of its `customAttributes`. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
bulkAddLabelsToCreators
PURPOSE: Create a Collection (a saved tag set) in the current workspace. A Collection is a workspace-scoped multi-select tag applied to items; once created you tag items into it with addItemToCollections and filter items by it. INPUT: - name (required string): the display name for the new Collection. Names are UNIQUE within the workspace, compared case-sensitively after trimming surrounding whitespace and invisible characters and NFC normalization (the name is stored in that form). NAME UNIQUENESS: if a Collection with the given name already exists, the call returns a duplicate-name userError (field ["input","name"]) and creates NOTHING. Do NOT invent a name variant ("Summer 2", "Summer_new") to work around it — REUSE the existing Collection instead: look it up with getCollections, take its id, and proceed with that id. AVAILABILITY: creating a Collection is only possible in workspaces whose Collections use the standard storage. In a workspace that stores Collections in an older format the call returns a schema-missing userError and creates nothing; there, create the Collection by tagging an item into it directly — addItemToCollections with collectionNames plus autoCreate: true creates the named Collection as part of the tagging call. OUTPUT: { collection: { id, name, itemCount } | null, userErrors: [{ field, message }] }. `collection.id` is the Collection's id in this workspace — pass it to addItemToCollections / removeItemFromCollections to tag items, and to searchItems(presetId:) or getCollection(id:) to read it. `collection` is null on a userErrors failure. `userErrors[].field` is an array of path segments (e.g. ["input","name"]). VERIFY AFTER WRITE: confirm the Collection landed with getCollection(id:) using the returned `collection.id`. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
createCollection
PURPOSE: Create a saved Content View in the current workspace. A Content View stores a filter set once; read its items later with searchItems(presetId:) instead of re-sending filters each call. COMPOSE WITH `filter` / `sorting` (typed, as in searchItems). To copy a view, send its getContentView `filters`, `sort`, and `customAttributeConditions` verbatim. INPUT: - name (required string): the display name. Names are NOT required to be unique — two content views may share a name. - filter (optional object): the typed filter (the same object searchItems `filter` takes), e.g. { "provider": "TIKTOK", "followersCount": { "from": 10000 } }. Stored as the equivalent `filters` blob. Send exactly one of filter / filters. - filters (optional object): the opaque filter blob, for cloning a get* output verbatim (see VIEW FILTERS below). Pass {} for a view with no filters (all items). Send exactly one of filter / filters. - customAttributeConditions (optional array): narrows the filter set (see CUSTOM ATTRIBUTE FILTERS below). Defaults to []. - sorting (optional array): the typed sort (the same list searchItems `sorting` takes), e.g. [{ "sortKey": "LIKE_COUNT", "sortOrder": "DESC" }]. Send at most one of sorting / sort. - sort (optional array): sort directives for cloning a get* output verbatim, e.g. [{ "field": "taken_at", "direction": "desc" }]. Defaults to []. - showReportingStats (optional boolean): whether reporting stats surface in the UI. Defaults to true. OUTPUT: { contentView: { id, name, filters, customAttributeConditions, sort, showReportingStats, group } | null, userErrors: [{ field, message }] }. `contentView.id` is the view's canonical FilterPreset UUID — pass it to searchItems(presetId:) to read its items, or to getContentView(id:) to read it back. `contentView` is null on a userErrors failure. `userErrors[].field` is an array of path segments (e.g. ["input","name"]). VERIFY AFTER WRITE: confirm the view landed with getContentView(id:) using the returned `contentView.id`. VIEW FILTERS (the `filters` blob): `filters` is a JSON object mapping filter keys to values, stored verbatim. Pass {} for "no filters". Unknown keys pass through. Enum-backed keys take the same enum names as searchItems `filter`. Stored values (such as "tiktok" or "Approved") are also accepted, in any letter case. An invalid value is rejected with a userError. To copy an existing view, clone its `filters` verbatim (fetch it with the matching get* tool). createContentView / updateContentView also take a typed `filter` (the same object searchItems `filter` takes) and `sorting`; PREFER them when composing a content view, and use `filters` / `sort` only to clone a get* output verbatim. CONTENT-VIEW keys (createContentView / updateContentView) — applied when the view is read via items(presetId:) / searchItems(presetId:): - item_types: array of FilterItemType names: POST, REEL, STORY, TIKTOK, TIKTOK_STORY, YOUTUBE, YOUTUBE_SHORT. - provider: one Provider name: INSTAGRAM, TIKTOK, INTERNAL, YOUTUBE. - content_types: array of MediaContentType names: IMAGE, VIDEO. - virality_score: array of FilterViralityScore names: HIGH, MEDIUM, LOW, NOT_VIRAL. - import_type: one FilterImportType name: MANUAL, AUTOMATIC. - social_profile_account_types: array of SocialProfileAccountType names: PERSONAL, CREATOR, BUSINESS. - usage_rights_status, instagram_whitelisting_status, tiktok_spark_code_status: each an array of FilterContractStatus names: APPROVED, EXPIRED, IN_QUEUE, REJECTED, REQUESTED. - tiktok_whitelisting_eligibility: one FilterTikTokWhitelistingEligibility name: ALL. - engagement: array of range entries whose "field" is a FilterEngagementField name: LIKE_COUNT, COMMENT_COUNT, MERGED_VIEW_PLAY_COUNT, SHARE_COUNT, ENGAGEMENTS_RATE, IMPRESSIONS_RATE, EARNED_MEDIA_VALUE. - super_search: object whose "mode" is a FilterSuperSearchMode name: EMBEDDING_CONTENT, FUZZY_TRANSCRIPTION, FUZZY_CAPTION. - taken_at: date range { "from": ISO8601, "to": ISO8601 }. - tags_names: array of hashtag / mention tag names. - campaigns_ids / collections_ids / social_profile_ids: arrays of ids. - account_names: array of profile handles. - followers_count: follower-count range { "from": int, "to": int }. - brand_related_only: true. SOCIAL-PROFILE-VIEW and CREATOR-VIEW `filters` (create/updateSocialProfileView, create/updateCreatorView): the blob is stored and echoed back by the get* tools, but it is NOT applied on read — socialProfiles(presetId:) / getSocialProfiles(presetId:) and creators(presetId:) / searchCreators(presetId:) narrow ONLY by the view's customAttributeConditions and sort. To narrow those views, use customAttributeConditions (see CUSTOM ATTRIBUTE CONDITIONS above); pass {} for filters unless cloning an existing view verbatim. Example content-view filters: { "item_types": ["REEL"], "provider": "INSTAGRAM", "taken_at": { "from": "2024-01-01", "to": "2024-12-31" } }. For anything not listed above (the other engagement and super_search fields, location filters, and any key you are unsure of), CLONE an existing view's `filters` — do NOT guess key names. CUSTOM ATTRIBUTE FILTERS (customAttributeConditions): Filter by the workspace's user-defined custom fields. An array of { field, operator, type, value } objects; multiple entries are AND-ed together. Step 1 - discover fields: call getCustomAttributeSchemas(entity: ITEM | CREATOR). Each schema returns `key` (use as `field`), `type` (use as `type`), and `options: [{ id, name }]` for select fields (use an option `id` as `value`). Step 2 - build each condition: - field : the schema `key` (e.g. "sentiment", "links"). - type : the schema `type`, UPPERCASE - one of TEXT, EMAIL, PHONE, URL, NUMBER, BOOLEAN, DATE, DATETIME, SINGLE_SELECT_V2, SINGLE_SELECT_V3, MULTIPLE_SELECT, MULTIPLE_SELECT_V2, TEXT_LIST, NUMBER_LIST, DATE_LIST, DATETIME_LIST, BOOLEAN_LIST. - operator : UPPERCASE; the valid set depends on the field's type group (see below). - value : depends on `type`: * TEXT / EMAIL / PHONE / URL -> a string. * SINGLE_SELECT_V2 / SINGLE_SELECT_V3 -> option `id` (UUID), or with no options in the schema (e.g. `sentiment`) the stored string ("Positive"). * NUMBER -> a number; BETWEEN takes { from, to }. * DATE / DATETIME -> ISO-8601 string; BETWEEN takes { from, to }. * BOOLEAN -> true / false. * MULTIPLE_SELECT / MULTIPLE_SELECT_V2 -> array of at least one option `id`. * TEXT_LIST / NUMBER_LIST / DATE_LIST / ... -> array of values. * IS_EMPTY / IS_NOT_EMPTY -> value is ignored; pass null. Operators by type group (an operator outside its group, or a SHIPPING_ADDRESS-typed condition, is rejected with an error naming the field): - Text & single-select (TEXT, EMAIL, PHONE, URL, SINGLE_SELECT_V2, SINGLE_SELECT_V3): IS, IS_NOT, CONTAINS, DOES_NOT_CONTAIN, STARTS_WITH, ENDS_WITH, IS_EMPTY, IS_NOT_EMPTY. (IS / IS_NOT are exact match on the select value described above.) - Number (NUMBER): EQUAL, NOT_EQUAL, MORE_THAN, MORE_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, BETWEEN, IS_EMPTY, IS_NOT_EMPTY. - Date (DATE, DATETIME): EQUAL, NOT_EQUAL, MORE_THAN, MORE_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, BETWEEN, IS_EMPTY, IS_NOT_EMPTY, IS_RELATIVE_TO_TODAY. IS_RELATIVE_TO_TODAY value: { relation: "past"|"this"|"next", period: "day"|"week"|"month"|"year" } with an optional whole-number offset (at most 100 years) and an optional IANA time zone "tz". - Boolean (BOOLEAN): IS (value true / false). - Multi-value (MULTIPLE_SELECT, MULTIPLE_SELECT_V2, and every *_LIST type): CONTAINS (matches ANY of the values, OR), CONTAINS_ALL (must contain ALL, AND), DOES_NOT_CONTAIN, IS_EMPTY, IS_NOT_EMPTY. NOTE: post_summary and shipping_address are stored but NOT indexed: positive operators match NOTHING, negated ones (IS_NOT, DOES_NOT_CONTAIN, IS_EMPTY) match EVERY record — read them from each item's `customAttributes` instead. NOTE: on items, `post_date` is the post time: DATE/DATETIME with a plain date (whole UTC day), datetime, { from, to } or IS_RELATIVE_TO_TODAY; NOT_EQUAL, IS_EMPTY and "$now" are rejected. `labels` takes the multi-value operators with label NAMES as values (its schema lists no options), matched CASE-SENSITIVELY, unlike the label tools. A blank `field` or an empty option list is rejected, as is a string value starting with "$" other than "$now". At most 20 conditions; a string value at most 256 characters; at most 50 values per list (500 option ids for a multi-select). Details: README §5.3. Examples: [{ "field": "sentiment", "operator": "IS", "type": "SINGLE_SELECT_V2", "value": "Positive" }] [{ "field": "links", "operator": "CONTAINS", "type": "TEXT_LIST", "value": ["https://example.com/promo"] }] [{ "field": "lead_score", "operator": "BETWEEN", "type": "NUMBER", "value": { "from": 10, "to": 100 } }] [{ "field": "notes", "operator": "IS_NOT_EMPTY", "type": "TEXT", "value": null }] WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
createContentView
PURPOSE: Create a saved Creator View in the current workspace. A Creator View saves a reusable narrowing (customAttributeConditions + sort) once; read its creators later with creators(presetId:). NOTE: the `filters` blob is stored and echoed back but NOT applied on read — creators(presetId:) narrows ONLY by customAttributeConditions + sort (see VIEW FILTERS below). Use customAttributeConditions to narrow results. CLONE FIRST (strongly preferred): the `filters` blob is opaque and easy to get subtly wrong. Before composing filters from scratch, fetch an existing Creator View with getCreatorViews (or getCreatorView(id:)), copy its `filters` value, and adapt it. A cloned-and-tweaked blob renders correctly in the app; a hand-built one may look successful here yet render broken. Only build filters from scratch for simple views, using the VIEW FILTERS contract below. INPUT: - name (required string): the display name. Names are NOT required to be unique — two Creator Views may share a name. - filters (required object): the opaque filter blob (see VIEW FILTERS below) — stored and echoed back but NOT applied on read. Pass {} unless cloning an existing view verbatim. - customAttributeConditions (optional array): narrows the filter set (see CUSTOM ATTRIBUTE FILTERS below). Defaults to []. - sort (optional array): sort directives, e.g. [{ "field": "created_at", "direction": "DESC" }]; `field` must be `created_at`, `full_name` or `id` (`id` always ascending), else a userError on ["input","sort"]. Defaults to []. - showReportingStats (optional boolean): whether reporting stats surface in the UI. Defaults to true. OUTPUT: { creatorView: { id, name, filters, customAttributeConditions, sort, showReportingStats, group } | null, userErrors: [{ field, message }] }. `creatorView.id` is the view's canonical FilterPreset UUID — pass it to creators(presetId:) to read its creators, or to getCreatorView(id:) to read it back. `creatorView` is null on a userErrors failure. `userErrors[].field` is an array of path segments (e.g. ["input","name"]). VERIFY AFTER WRITE: confirm the view landed with getCreatorView(id:) using the returned `creatorView.id`. VIEW FILTERS (the `filters` blob): `filters` is a JSON object mapping filter keys to values, stored verbatim. Pass {} for "no filters". Unknown keys pass through. Enum-backed keys take the same enum names as searchItems `filter`. Stored values (such as "tiktok" or "Approved") are also accepted, in any letter case. An invalid value is rejected with a userError. To copy an existing view, clone its `filters` verbatim (fetch it with the matching get* tool). createContentView / updateContentView also take a typed `filter` (the same object searchItems `filter` takes) and `sorting`; PREFER them when composing a content view, and use `filters` / `sort` only to clone a get* output verbatim. CONTENT-VIEW keys (createContentView / updateContentView) — applied when the view is read via items(presetId:) / searchItems(presetId:): - item_types: array of FilterItemType names: POST, REEL, STORY, TIKTOK, TIKTOK_STORY, YOUTUBE, YOUTUBE_SHORT. - provider: one Provider name: INSTAGRAM, TIKTOK, INTERNAL, YOUTUBE. - content_types: array of MediaContentType names: IMAGE, VIDEO. - virality_score: array of FilterViralityScore names: HIGH, MEDIUM, LOW, NOT_VIRAL. - import_type: one FilterImportType name: MANUAL, AUTOMATIC. - social_profile_account_types: array of SocialProfileAccountType names: PERSONAL, CREATOR, BUSINESS. - usage_rights_status, instagram_whitelisting_status, tiktok_spark_code_status: each an array of FilterContractStatus names: APPROVED, EXPIRED, IN_QUEUE, REJECTED, REQUESTED. - tiktok_whitelisting_eligibility: one FilterTikTokWhitelistingEligibility name: ALL. - engagement: array of range entries whose "field" is a FilterEngagementField name: LIKE_COUNT, COMMENT_COUNT, MERGED_VIEW_PLAY_COUNT, SHARE_COUNT, ENGAGEMENTS_RATE, IMPRESSIONS_RATE, EARNED_MEDIA_VALUE. - super_search: object whose "mode" is a FilterSuperSearchMode name: EMBEDDING_CONTENT, FUZZY_TRANSCRIPTION, FUZZY_CAPTION. - taken_at: publication-date range { "from": ISO8601, "to": ISO8601 }. - tags_names: array of hashtag / mention tag names. - campaigns_ids / collections_ids (from getCollections) / social_profile_ids: arrays of ids. - account_names: array of social profile handles. - followers_count: follower-count range { "from": int, "to": int }. SOCIAL-PROFILE-VIEW and CREATOR-VIEW `filters` (create/updateSocialProfileView, create/updateCreatorView): the blob is stored and echoed back by the get* tools, but it is NOT applied on read — socialProfiles(presetId:) / getSocialProfiles(presetId:) and creators(presetId:) / searchCreators(presetId:) narrow ONLY by the view's customAttributeConditions and sort. To narrow those views, use customAttributeConditions (see CUSTOM ATTRIBUTE CONDITIONS above); pass {} for filters unless cloning an existing view verbatim. Example content-view filters: { "item_types": ["REEL"], "provider": "INSTAGRAM", "taken_at": { "from": "2024-01-01", "to": "2024-12-31" } }. For anything not listed above (the other engagement and super_search fields, location filters, and any key you are unsure of), CLONE an existing view's `filters` — do NOT guess key names. CUSTOM ATTRIBUTE FILTERS (customAttributeConditions): Filter by the workspace's user-defined custom fields. An array of { field, operator, type, value } objects; multiple entries are AND-ed together. Step 1 - discover fields: call getCustomAttributeSchemas(entity: ITEM | CREATOR). Each schema returns `key` (use as `field`), `type` (use as `type`), and `options: [{ id, name }]` for select fields (use an option `id` as `value`). Step 2 - build each condition: - field : the schema `key` (e.g. "sentiment", "links"). - type : the schema `type`, UPPERCASE - one of TEXT, EMAIL, PHONE, URL, NUMBER, BOOLEAN, DATE, DATETIME, SINGLE_SELECT_V2, SINGLE_SELECT_V3, MULTIPLE_SELECT, MULTIPLE_SELECT_V2, TEXT_LIST, NUMBER_LIST, DATE_LIST, DATETIME_LIST, BOOLEAN_LIST. - operator : UPPERCASE; the valid set depends on the field's type group (see below). - value : depends on `type`: * TEXT / EMAIL / PHONE / URL -> a string. * SINGLE_SELECT_V2 / SINGLE_SELECT_V3 -> the chosen option `id` (UUID). * NUMBER -> a number; BETWEEN takes { from, to }. * DATE / DATETIME -> ISO-8601 string; BETWEEN takes { from, to }. * BOOLEAN -> true / false. * MULTIPLE_SELECT / MULTIPLE_SELECT_V2 -> array of at least one option `id`. * TEXT_LIST / NUMBER_LIST / DATE_LIST / ... -> array of values. * IS_EMPTY / IS_NOT_EMPTY -> value is ignored; pass null. Operators by type group (an operator outside its group, or a SHIPPING_ADDRESS-typed condition, is rejected with an error naming the field): - Text & single-select (TEXT, EMAIL, PHONE, URL, SINGLE_SELECT_V2, SINGLE_SELECT_V3): IS, IS_NOT, CONTAINS, DOES_NOT_CONTAIN, STARTS_WITH, ENDS_WITH, IS_EMPTY, IS_NOT_EMPTY. (IS / IS_NOT are exact match - for a select field, value is the option id.) - Number (NUMBER): EQUAL, NOT_EQUAL, MORE_THAN, MORE_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, BETWEEN, IS_EMPTY, IS_NOT_EMPTY. - Date (DATE, DATETIME): EQUAL, NOT_EQUAL, MORE_THAN, MORE_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, BETWEEN, IS_EMPTY, IS_NOT_EMPTY, IS_RELATIVE_TO_TODAY. IS_RELATIVE_TO_TODAY value: { relation: "past"|"this"|"next", period: "day"|"week"|"month"|"year" } with an optional whole-number offset (at most 100 years) and an optional IANA time zone "tz". - Boolean (BOOLEAN): IS (value true / false). - Multi-value (MULTIPLE_SELECT, MULTIPLE_SELECT_V2, and every *_LIST type): CONTAINS (matches ANY of the values, OR), CONTAINS_ALL (must contain ALL, AND), DOES_NOT_CONTAIN, IS_EMPTY, IS_NOT_EMPTY. NOTE: post_summary and shipping_address are stored but NOT indexed: positive operators match NOTHING, negated ones (IS_NOT, DOES_NOT_CONTAIN, IS_EMPTY) match EVERY record — read them from each item's `customAttributes` instead. NOTE: on items, `post_date` is the post time: DATE/DATETIME with a plain date (whole UTC day), datetime, { from, to } or IS_RELATIVE_TO_TODAY; NOT_EQUAL, IS_EMPTY and "$now" are rejected. `labels` takes the multi-value operators. A blank `field` or an empty option list is rejected, as is a string value starting with "$" other than "$now". At most 20 conditions; a string value at most 256 characters; at most 50 values per list (500 option ids for a multi-select). Details: README §5.3. Examples: [{ "field": "sentiment", "operator": "IS", "type": "SINGLE_SELECT_V2", "value": "<option-uuid>" }] [{ "field": "links", "operator": "CONTAINS", "type": "TEXT_LIST", "value": ["https://example.com/promo"] }] [{ "field": "lead_score", "operator": "BETWEEN", "type": "NUMBER", "value": { "from": 10, "to": 100 } }] [{ "field": "notes", "operator": "IS_NOT_EMPTY", "type": "TEXT", "value": null }] WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
createCreatorView
PURPOSE: Creates labels in the workspace's creator label taxonomy. Names already present (ignoring case and surrounding whitespace) are returned unchanged — creating an existing label is a no-op, not an error. Repeating the call is safe. Creating a label does not assign it to anyone; use addLabelsToCreators for that. Labels have no id; the name is the identity. INPUT: - labelNames (required array of strings, 1-50, each at most 100 characters): the names to create. A blank name is a userError on ["labelNames"]. BEING DELETED: A label with `deleting: true` is being removed; do not assign it, and do not recreate it until it disappears from getLabels. Creating such a name is a userError. OUTPUT: { labels: [{ name, deleting }], userErrors: [{ field, message }] }. `labels` holds the stored spelling of every submitted name, one entry per name ignoring case, and is empty when userErrors is non-empty. Lock contention with another write is an error to retry, not a userError. VERIFY AFTER WRITE: call getLabels — the returned spellings are listed immediately. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
createLabels
PURPOSE: Create a saved Social Profile view in the current workspace. A Social Profile view stores a filter set once; read its profiles later with getSocialProfiles(presetId:) instead of re-sending filters each call. CLONE FIRST (strongly preferred): the `filters` blob is opaque and easy to get subtly wrong. Before composing filters from scratch, fetch an existing Social Profile view with getSocialProfileViews (or getSocialProfileView(id:)), copy its `filters` value, and adapt it. A cloned-and-tweaked blob renders correctly in the app; a hand-built one may look successful here yet render broken. Only build filters from scratch for simple views, using the VIEW FILTERS contract below. INPUT: - name (required string): the display name. Names are NOT required to be unique — two Social Profile views may share a name. - filters (required object): the opaque filter blob (see VIEW FILTERS below). Pass {} for a view with no filters (all profiles). - customAttributeConditions (optional array): narrows the filter set (see CUSTOM ATTRIBUTE FILTERS below). Defaults to []. - sort (optional array): sort directives. Defaults to []. - showReportingStats (optional boolean): whether reporting stats surface in the UI. Defaults to true. OUTPUT: { socialProfileView: { id, name, filters, customAttributeConditions, sort, showReportingStats, group } | null, userErrors: [{ field, message }] }. `socialProfileView.id` is the view's canonical FilterPreset UUID — pass it to getSocialProfiles(presetId:) to read its profiles, or to getSocialProfileView(id:) to read it back. `socialProfileView` is null on a userErrors failure. `userErrors[].field` is an array of path segments (e.g. ["input","name"]). VERIFY AFTER WRITE: confirm the view landed with getSocialProfileView(id:) using the returned `socialProfileView.id`. VIEW FILTERS (the `filters` blob): `filters` is a JSON object mapping filter keys to values, stored verbatim. Pass {} for "no filters". Unknown keys pass through. Enum-backed keys take the same enum names as searchItems `filter`. Stored values (such as "tiktok" or "Approved") are also accepted, in any letter case. An invalid value is rejected with a userError. To copy an existing view, clone its `filters` verbatim (fetch it with the matching get* tool). createContentView / updateContentView also take a typed `filter` (the same object searchItems `filter` takes) and `sorting`; PREFER them when composing a content view, and use `filters` / `sort` only to clone a get* output verbatim. CONTENT-VIEW keys (createContentView / updateContentView) — applied when the view is read via items(presetId:) / searchItems(presetId:): - item_types: array of FilterItemType names: POST, REEL, STORY, TIKTOK, TIKTOK_STORY, YOUTUBE, YOUTUBE_SHORT. - provider: one Provider name: INSTAGRAM, TIKTOK, INTERNAL, YOUTUBE. - content_types: array of MediaContentType names: IMAGE, VIDEO. - virality_score: array of FilterViralityScore names: HIGH, MEDIUM, LOW, NOT_VIRAL. - import_type: one FilterImportType name: MANUAL, AUTOMATIC. - social_profile_account_types: array of SocialProfileAccountType names: PERSONAL, CREATOR, BUSINESS. - usage_rights_status, instagram_whitelisting_status, tiktok_spark_code_status: each an array of FilterContractStatus names: APPROVED, EXPIRED, IN_QUEUE, REJECTED, REQUESTED. - tiktok_whitelisting_eligibility: one FilterTikTokWhitelistingEligibility name: ALL. - engagement: array of range entries whose "field" is a FilterEngagementField name: LIKE_COUNT, COMMENT_COUNT, MERGED_VIEW_PLAY_COUNT, SHARE_COUNT, ENGAGEMENTS_RATE, IMPRESSIONS_RATE, EARNED_MEDIA_VALUE. - super_search: object whose "mode" is a FilterSuperSearchMode name: EMBEDDING_CONTENT, FUZZY_TRANSCRIPTION, FUZZY_CAPTION. - taken_at: publication-date range { "from": ISO8601, "to": ISO8601 }. - tags_names: array of hashtag / mention tag names. - campaigns_ids / collections_ids (from getCollections) / social_profile_ids: arrays of ids. - account_names: array of social profile handles. - followers_count: follower-count range { "from": int, "to": int }. SOCIAL-PROFILE-VIEW and CREATOR-VIEW `filters` (create/updateSocialProfileView, create/updateCreatorView): the blob is stored and echoed back by the get* tools, but it is NOT applied on read — socialProfiles(presetId:) / getSocialProfiles(presetId:) and creators(presetId:) / searchCreators(presetId:) narrow ONLY by the view's customAttributeConditions and sort. To narrow those views, use customAttributeConditions (see CUSTOM ATTRIBUTE CONDITIONS above); pass {} for filters unless cloning an existing view verbatim. Example content-view filters: { "item_types": ["REEL"], "provider": "INSTAGRAM", "taken_at": { "from": "2024-01-01", "to": "2024-12-31" } }. For anything not listed above (the other engagement and super_search fields, location filters, and any key you are unsure of), CLONE an existing view's `filters` — do NOT guess key names. CUSTOM ATTRIBUTE FILTERS (customAttributeConditions): Filter by the workspace's user-defined custom fields. An array of { field, operator, type, value } objects; multiple entries are AND-ed together. Step 1 - discover fields: call getCustomAttributeSchemas(entity: ITEM | CREATOR). Each schema returns `key` (use as `field`), `type` (use as `type`), and `options: [{ id, name }]` for select fields (use an option `id` as `value`). Step 2 - build each condition: - field : the schema `key` (e.g. "sentiment", "links"). - type : the schema `type`, UPPERCASE - one of TEXT, EMAIL, PHONE, URL, NUMBER, BOOLEAN, DATE, DATETIME, SINGLE_SELECT_V2, SINGLE_SELECT_V3, MULTIPLE_SELECT, MULTIPLE_SELECT_V2, TEXT_LIST, NUMBER_LIST, DATE_LIST, DATETIME_LIST, BOOLEAN_LIST. - operator : UPPERCASE; the valid set depends on the field's type group (see below). - value : depends on `type`: * TEXT / EMAIL / PHONE / URL -> a string. * SINGLE_SELECT_V2 / SINGLE_SELECT_V3 -> the chosen option `id` (UUID). * NUMBER -> a number; BETWEEN takes { from, to }. * DATE / DATETIME -> ISO-8601 string; BETWEEN takes { from, to }. * BOOLEAN -> true / false. * MULTIPLE_SELECT / MULTIPLE_SELECT_V2 -> array of at least one option `id`. * TEXT_LIST / NUMBER_LIST / DATE_LIST / ... -> array of values. * IS_EMPTY / IS_NOT_EMPTY -> value is ignored; pass null. Operators by type group (an operator outside its group, or a SHIPPING_ADDRESS-typed condition, is rejected with an error naming the field): - Text & single-select (TEXT, EMAIL, PHONE, URL, SINGLE_SELECT_V2, SINGLE_SELECT_V3): IS, IS_NOT, CONTAINS, DOES_NOT_CONTAIN, STARTS_WITH, ENDS_WITH, IS_EMPTY, IS_NOT_EMPTY. (IS / IS_NOT are exact match - for a select field, value is the option id.) - Number (NUMBER): EQUAL, NOT_EQUAL, MORE_THAN, MORE_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, BETWEEN, IS_EMPTY, IS_NOT_EMPTY. - Date (DATE, DATETIME): EQUAL, NOT_EQUAL, MORE_THAN, MORE_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, BETWEEN, IS_EMPTY, IS_NOT_EMPTY, IS_RELATIVE_TO_TODAY. IS_RELATIVE_TO_TODAY value: { relation: "past"|"this"|"next", period: "day"|"week"|"month"|"year" } with an optional whole-number offset (at most 100 years) and an optional IANA time zone "tz". - Boolean (BOOLEAN): IS (value true / false). - Multi-value (MULTIPLE_SELECT, MULTIPLE_SELECT_V2, and every *_LIST type): CONTAINS (matches ANY of the values, OR), CONTAINS_ALL (must contain ALL, AND), DOES_NOT_CONTAIN, IS_EMPTY, IS_NOT_EMPTY. NOTE: post_summary and shipping_address are stored but NOT indexed: positive operators match NOTHING, negated ones (IS_NOT, DOES_NOT_CONTAIN, IS_EMPTY) match EVERY record — read them from each item's `customAttributes` instead. NOTE: on items, `post_date` is the post time: DATE/DATETIME with a plain date (whole UTC day), datetime, { from, to } or IS_RELATIVE_TO_TODAY; NOT_EQUAL, IS_EMPTY and "$now" are rejected. `labels` takes the multi-value operators. A blank `field` or an empty option list is rejected, as is a string value starting with "$" other than "$now". At most 20 conditions; a string value at most 256 characters; at most 50 values per list (500 option ids for a multi-select). Details: README §5.3. Examples: [{ "field": "sentiment", "operator": "IS", "type": "SINGLE_SELECT_V2", "value": "<option-uuid>" }] [{ "field": "links", "operator": "CONTAINS", "type": "TEXT_LIST", "value": ["https://example.com/promo"] }] [{ "field": "lead_score", "operator": "BETWEEN", "type": "NUMBER", "value": { "from": 10, "to": 100 } }] [{ "field": "notes", "operator": "IS_NOT_EMPTY", "type": "TEXT", "value": null }] WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
createSocialProfileView
PURPOSE: Create a user-created view group in the current workspace. A view group is a workspace-scoped sidebar bucket that Content Views, Social Profile Views, workspace Creator Views, and Collections can be moved into (with moveContentViewToGroup / moveSocialProfileViewToGroup / moveCreatorViewToGroup / moveCollectionToGroup). CAMPAIGN Creator Views are NEVER group members — they are campaign-scoped, not workspace-scoped. INPUT: - name (required string): the display name for the new group. Names are UNIQUE within the workspace, compared case-sensitively after trimming surrounding whitespace and invisible characters and NFC normalization (the name is stored in that form). Names that differ only by invisible characters or spacing (a no-break space, a double space) count as the same. NAME UNIQUENESS: if a group with the given name already exists, the call returns a validation_error userError (field ["input","name"]) and creates NOTHING. Do NOT invent a name variant ("Team 2", "Team_new") to work around it — REUSE the existing group instead: look it up with getViewGroups, take its id, and move views into it with the move tools. OUTPUT: { viewGroup: { id, name, contentViews, socialProfileViews, creatorViews, collections } | null, userErrors: [{ field, message }] }. `viewGroup.id` is the group's canonical UUID — pass it as `groupId` to moveContentViewToGroup / moveSocialProfileViewToGroup / moveCreatorViewToGroup / moveCollectionToGroup to fill it, to reorderViewsInGroup to order its members, or to getViewGroup(id:) to read it back. A freshly created group has empty `contentViews` / `socialProfileViews` / `creatorViews` / `collections`. `viewGroup` is null on a userErrors failure. `userErrors[].field` is an array of path segments (e.g. ["input","name"]). VERIFY AFTER WRITE: confirm the group landed with getViewGroup(id:) using the returned `viewGroup.id`. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
createViewGroup
PURPOSE: Create an outbound-webhook subscription in the current workspace. New items landing in the subscribed content view(s) trigger a signed HTTPS POST to your endpoint. INPUT: - name (required string): display name for the subscription. - url (required string): the HTTPS endpoint deliveries are POSTed to. Must be HTTPS and pass SSRF validation (no private / link-local hosts) — a bad url returns a userError on ["input","url"]. - viewIds (array of strings): content-view (FilterPreset) UUIDs whose new items trigger deliveries. REQUIRED (at least one, each owned by this workspace — resolve ids with getContentViews first) whenever content_view.item_added is subscribed; omit it when only operation.completed is. Omitting it with a view-scoped type returns a viewIds userError on ["input","viewIds"]. - eventTypes (optional array of strings): event types to subscribe to. Defaults to ["content_view.item_added"]; operation.completed fires once per finished operation. - metadata (optional object): opaque metadata echoed back in each delivery payload. Max 4KB serialized. Defaults to {}. DUPLICATES: creating an exact duplicate (same url AND same event types AND same viewIds as an existing subscription, in any status) returns a userError on ["input","url"] naming the existing subscription id instead of creating a second subscription. Reusing a url and event types for a DIFFERENT set of viewIds is allowed — those deliver different views. PARTIAL OVERLAP IS NOT BLOCKED: a viewId present in two subscriptions on the same url is delivered once PER subscription, so that url receives the same event twice. Check getWebhookSubscriptions before reusing a url, and prefer editing the existing subscription's viewIds over creating an overlapping one. SIGNING SECRET (store it now — shown ONCE): the response `secret` (whsec_...) is returned in plaintext ONLY here and from rotateWebhookSubscriptionSecret. It is stored encrypted and NEVER returned again. Relay it to the user immediately and instruct them to save it; there is no way to recover it later (they would have to rotate). TIER LIMITS: the workspace's plan caps the number of subscriptions and views-per-subscription (a violation returns a userError whose message states the limit and current usage). OUTPUT: { webhookSubscription: { id, name, url, viewIds, eventTypes, metadata, status } | null, secret: string | null, userErrors: [{ field, message }] }. `webhookSubscription` and `secret` are both null on a userErrors failure. `userErrors[].field` is an array of path segments (e.g. ["input","url"], ["input","viewIds"]). VERIFY AFTER WRITE: confirm the subscription via getWebhookSubscriptions (the WebhookSubscription type never re-exposes the secret). WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
createWebhookSubscription
PURPOSE: Delete a Collection (a saved tag set) from the current workspace. This is a HARD, IRREVERSIBLE delete. WHAT IS DESTROYED: the Collection itself — its tag set and every tag association, so the tag is stripped from every item it was applied to and can no longer be used as a filter. WHAT SURVIVES: the ITEMS ARE NEVER DELETED — they lose only this one tag; every other tag, field, and piece of data on them is untouched. INPUT: - id (required string): the Collection's id, as returned by getCollections / createCollection for this workspace. Resolve ids with getCollections first — NEVER guess a Collection id. CONFIRM BEFORE CALLING: because this is IRREVERSIBLE, first fetch the Collection with getCollection(id:) and CONFIRM WITH THE USER, echoing the Collection's name back to them, before you call this tool. FAILURES: an unknown id, an already-deleted id, or an id owned by another workspace returns a not_found userError (field ["id"]) with `deletedCollectionId: null` — deleting an already-deleted Collection is a safe no-op (idempotent). Same observable for unknown vs cross-workspace, on purpose (no existence leak). AVAILABILITY: Collection management is available only in workspaces whose Collections use the standard storage. In a workspace that stores Collections in an older format, the ids getCollections returns are not accepted here and the call returns a userError without changing anything. OUTPUT: { deletedCollectionId: string | null, userErrors: [{ field, message }] }. `deletedCollectionId` echoes the deleted id on success, or is null when the Collection was not found. `userErrors[].field` is an array of path segments (e.g. ["id"]). VERIFY AFTER DELETE: confirm removal with getCollection(id:) — it returns null once the Collection is gone. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
deleteCollection
PURPOSE: Delete a saved Content View from the current workspace. This is a HARD, IRREVERSIBLE delete. WHAT IS DESTROYED: the saved view itself — its stored filters, sort, and settings. It disappears from the workspace's saved views. WHAT SURVIVES: the underlying CONTENT IS NEVER DELETED — the items the view listed remain in the workspace untouched; only this saved filter configuration is removed. INPUT: - id (required string): the view's canonical FilterPreset UUID (as returned by getContentViews / createContentView). Resolve ids with getContentViews first — NEVER guess. CONFIRM BEFORE CALLING: because this is IRREVERSIBLE, first fetch the view with getContentView(id:) and CONFIRM WITH THE USER, echoing the view's name back to them, before you call this tool. FAILURES: an unknown id, an already-deleted id, or an id owned by another workspace returns a not_found userError (field ["id"]) with `deletedContentViewId: null` — deleting an already-deleted view is a safe no-op (idempotent). Same observable for unknown vs cross-workspace, on purpose (no existence leak). OUTPUT: { deletedContentViewId: string | null, userErrors: [{ field, message }] }. `deletedContentViewId` echoes the deleted id on success, or is null when the view was not found. `userErrors[].field` is an array of path segments (e.g. ["id"]). VERIFY AFTER DELETE: confirm removal with getContentView(id:) — it returns null once the view is gone. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
deleteContentView
PURPOSE: Delete a saved Creator View from the current workspace. This is a HARD, IRREVERSIBLE delete. WHAT IS DESTROYED: the saved view itself — its stored filters, sort, and settings. It disappears from the workspace's saved views. WHAT SURVIVES: the underlying CREATORS ARE NEVER DELETED — the creators the view listed remain in the workspace untouched; only this saved filter configuration is removed. INPUT: - id (required string): the view's canonical FilterPreset UUID (as returned by getCreatorViews / createCreatorView). Resolve ids with getCreatorViews first — NEVER guess. CONFIRM BEFORE CALLING: because this is IRREVERSIBLE, first fetch the view with getCreatorView(id:) and CONFIRM WITH THE USER, echoing the view's name back to them, before you call this tool. FAILURES: an unknown id, an already-deleted id, or an id owned by another workspace returns a not_found userError (field ["id"]) with `deletedCreatorViewId: null` — deleting an already-deleted view is a safe no-op (idempotent). Same observable for unknown vs cross-workspace, on purpose (no existence leak). OUTPUT: { deletedCreatorViewId: string | null, userErrors: [{ field, message }] }. `deletedCreatorViewId` echoes the deleted id on success, or is null when the view was not found. `userErrors[].field` is an array of path segments (e.g. ["id"]). VERIFY AFTER DELETE: confirm removal with getCreatorView(id:) — it returns null once the view is gone. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
deleteCreatorView
PURPOSE: Permanently deletes the label from the whole workspace and removes it from every creator that carries it; the creators themselves are kept. This is irreversible and completes in the background — confirm with the user, echoing the label name, before calling. IRREVERSIBLE, workspace-wide. WHAT IS DESTROYED: the label itself, across the whole workspace — it leaves the label taxonomy AND is stripped from every creator that carries it, in every spelling that matches (matching ignores case and surrounding whitespace). WHAT SURVIVES: the CREATORS ARE NEVER DELETED — only the label value is removed from them. Every other label, campaign, collection and view is untouched. INPUT: - labelName (required string): the label to delete, exactly as getLabels returned it. Resolve the spelling with getLabels first — never guess. Not length-limited: a name too long to create may still exist and stays deletable. A blank name is a userError on ["labelName"]. CONFIRM BEFORE CALLING: list the labels with getLabels and CONFIRM WITH THE USER, echoing the label name back to them, before you call this tool. SCHEDULED, NOT IMMEDIATE: deletion is eventual. The label stays in getLabels (it shows `deleting: true` once the background run has marked it) and may remain in creator `customAttributes.labels` and in search until the deletion completes. Calling again while a deletion is in flight returns `scheduled: true` with the same operationId. FAILURES: a name that matches nothing in this workspace is a userError on ["labelName"] with `scheduled: false`; nothing is scheduled. The not-found check is best-effort: a concurrent delete may still yield `scheduled: true`. Lock contention or a scheduling outage is an error result, not a userError: retry it, and the retry resumes the same deletion. OUTPUT: { scheduled, operationId, labelName, userErrors: [{ field, message }] }. `labelName` echoes the name you submitted; `operationId` is null when userErrors is non-empty. VERIFY AFTER DELETE: poll getLabels until the name is ABSENT; follow progress with getOperation(id: operationId) until COMPLETED — its succeeded/failed/pending counts are always 0 for a label operation; read status, total and processed. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
deleteLabel
PURPOSE: Delete a saved Social Profile view from the current workspace. This is a HARD, IRREVERSIBLE delete. WHAT IS DESTROYED: the saved view itself — its stored filters, sort, and settings. It disappears from the workspace's saved views. WHAT SURVIVES: the underlying SOCIAL PROFILES ARE NEVER DELETED — the profiles the view listed remain in the workspace untouched; only this saved filter configuration is removed. INPUT: - id (required string): the view's canonical FilterPreset UUID (as returned by getSocialProfileViews / createSocialProfileView). Resolve ids with getSocialProfileViews first — NEVER guess. CONFIRM BEFORE CALLING: because this is IRREVERSIBLE, first fetch the view with getSocialProfileView(id:) and CONFIRM WITH THE USER, echoing the view's name back to them, before you call this tool. FAILURES: an unknown id, an already-deleted id, or an id owned by another workspace returns a not_found userError (field ["id"]) with `deletedSocialProfileViewId: null` — deleting an already-deleted view is a safe no-op (idempotent). Same observable for unknown vs cross-workspace, on purpose (no existence leak). OUTPUT: { deletedSocialProfileViewId: string | null, userErrors: [{ field, message }] }. `deletedSocialProfileViewId` echoes the deleted id on success, or is null when the view was not found. `userErrors[].field` is an array of path segments (e.g. ["id"]). VERIFY AFTER DELETE: confirm removal with getSocialProfileView(id:) — it returns null once the view is gone. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
deleteSocialProfileView
PURPOSE: Delete a view group from the current workspace. This is a HARD, IRREVERSIBLE delete. WHAT IS DESTROYED: the view group itself — the sidebar bucket and its membership rows. It disappears from the workspace's groups. WHAT SURVIVES: the MEMBERS ARE NEVER DELETED — every Content View, Social Profile View, Creator View, and Collection that was in the group becomes ungrouped. Their FilterPreset UUIDs are returned as `movedViewIds` so you can re-file them into another group if you want. INPUT: - id (required string): the view group's UUID (as returned by getViewGroups / createViewGroup). Resolve ids with getViewGroups first — NEVER guess a group id. CONFIRM BEFORE CALLING: because this is IRREVERSIBLE, first fetch the group with getViewGroup(id:) and CONFIRM WITH THE USER, echoing the group's name back to them, before you call this tool. FAILURES: an unknown id, an already-deleted id, or an id owned by another workspace returns a not_found userError (field ["id"]) with `deletedViewGroupId: null` and `movedViewIds: []` — deleting an already-deleted group is a safe no-op (idempotent). Same observable for unknown vs cross-workspace, on purpose (no existence leak). OUTPUT: { deletedViewGroupId: string | null, movedViewIds: [string], userErrors: [{ field, message }] }. `deletedViewGroupId` echoes the deleted id on success, or is null when the group was not found. `movedViewIds` lists the FilterPreset UUIDs of the views and Collections that were ungrouped (empty on not-found or when the group had no members) — invalidate any cached ContentView / SocialProfileView / CreatorView / Collection rows in this list. `userErrors[].field` is an array of path segments (e.g. ["id"]). VERIFY AFTER DELETE: confirm removal with getViewGroup(id:) — it returns null once the group is gone. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
deleteViewGroup
PURPOSE: Delete a webhook subscription from the current workspace. This is a HARD, IRREVERSIBLE delete. WHAT IS DESTROYED: the subscription itself AND all of its delivery records (the deliveries cascade). The endpoint stops receiving any further events immediately. WHAT SURVIVES: the content views the subscription pointed at are NEVER deleted — only this subscription (and its delivery history) is removed. INPUT: - id (required string): the subscription's UUID (as returned by getWebhookSubscriptions). Resolve ids with getWebhookSubscriptions first — NEVER guess. CONFIRM BEFORE CALLING: because this is IRREVERSIBLE, first look up the subscription and CONFIRM WITH THE USER, echoing the subscription's name/url back to them, before you call this tool. FAILURES: an unknown id, an already-deleted id, or an id owned by another workspace returns a not_found userError (field ["id"]) with `deletedWebhookSubscriptionId: null` — deleting an already-deleted subscription is a safe no-op (idempotent). Same observable for unknown vs cross-workspace, on purpose (no existence leak). OUTPUT: { deletedWebhookSubscriptionId: string | null, userErrors: [{ field, message }] }. `deletedWebhookSubscriptionId` echoes the deleted id on success, or is null when the subscription was not found. `userErrors[].field` is an array of path segments (e.g. ["id"]). VERIFY AFTER DELETE: confirm removal by calling getWebhookSubscriptions — the id is gone. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
deleteWebhookSubscription
PURPOSE: Re-enable a webhook subscription in the current workspace that was AUTO-DISABLED by repeated delivery failures (status DISABLED_BY_FAILURES). Clears the failure counters and, by default, replays the last 24h of terminal FAILED deliveries (nextAttemptAt null) one-shot per row (one more attempt each, lifetime attemptCount preserved, no backoff-ladder reset) — a bounded catch-up, never a retry storm. A FAILED delivery still awaiting its scheduled retry (nextAttemptAt set) is left to the automatic retry, and `subscription.ping` deliveries are never replayed. A replayed delivery keeps its lastError / lastResponseStatus until the replay settles. INPUT: - id (required string): the failure-disabled subscription's UUID. Resolve it via getWebhookSubscriptions first (look for status DISABLED_BY_FAILURES) — never guess. - replayFailedSince24h (optional boolean, default true): when true, replays each terminal failed delivery from the last 24h once. Pass false to re-enable WITHOUT replaying the backlog. ONLY DISABLED_BY_FAILURES SUBSCRIPTIONS ARE ENABLEABLE: a subscription in any other status (active / disabled_by_user) returns a not_disabled_by_failures userError (field ["id"]) and changes nothing. An already-enabled subscription is no longer DISABLED_BY_FAILURES, so re-calling is a safe no-op not_disabled_by_failures (this is what makes the tool idempotent-safe). To resume a user-paused (DISABLED_BY_USER) subscription, use updateWebhookSubscription with status ACTIVE. FAILURES: an unknown id, or a subscription owned by another workspace, returns a not_found userError (field ["id"]) — same observable on purpose (no cross-workspace existence leak). RATE LIMIT: a re-enable within 5 minutes of the auto-disable returns a userError (field ["id"]) "Rate limit exceeded. Retry after N seconds." and changes nothing — wait the stated seconds and retry. OUTPUT: { webhookSubscription: { id, name, url, viewIds, eventTypes, metadata, status, consecutiveFailures, lastSuccessAt, disabledAt } | null, userErrors: [{ field, message }] }. On success `webhookSubscription.status` is `ACTIVE` and `consecutiveFailures` is 0. `webhookSubscription` is null on a not_found / not_disabled_by_failures / rate-limited failure. `userErrors[].field` is an array of path segments. VERIFY AFTER WRITE: confirm by calling getWebhookSubscriptions (status back to ACTIVE); if you replayed, poll getWebhookDeliveries (filter by subscriptionId) for the catch-up attempts settling. WRITE NOTES (apply to every write tool): - userErrors report domain rejections in a SUCCESSFUL tool result, NOT a crash. Atomicity is tool-specific: valid changes may apply alongside errors. Read each `field` path and `message` plus returned state; verify what applied before retrying rejected work. - Verify after write: after a success, confirm the change with the READ tool this tool's own description names (e.g. a get*/search* tool) before reporting success to the user. Deletes are confirmed when that read returns null. - Retry discipline on a timeout / transport error (you cannot tell if the write landed): `idempotentHint: true` tools MAY be retried within their documented guarantee. For every OTHER write, READ FIRST with its verify tools, including queued operations, before retrying. NEVER blind-retry non-idempotent create tools, uploadItemFromUrl or refetchEngagementBulk: duplicates create entities/imports or re-spend credits. - Destructive tools (`destructiveHint: true`) CHANGE OR REMOVE data that already exists, or trigger a real delivery attempt — they are not purely additive. Say what will change before you call one. Being destructive does NOT on its own require a confirmation round-trip; only the IRREVERSIBLE tools named below do. - IRREVERSIBLE tools — every delete*, plus mergeLabels, rotateWebhookSubscriptionSecret (the previous signing secret is gone for good) and refetchEngagementBulk (credits for refreshed items are not refunded): CONFIRM WITH THE USER first, echoing the target entity's name/id back to them, and state that the effect is IRREVERSIBLE, before you call. No other write tool needs a confirmation round-trip. - Cost: a write costs 50 + 1 per selected payload field unless its description states its own price, charged against the workspace's shared rate-limit bucket; the per-workspace throttle (below) applies. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
enableWebhookSubscription
PURPOSE: Check a Deep Research report before starting it: validates the input exactly as createDeepResearchReport would and returns its cost and whether the workspace can afford it. Creates nothing and spends nothing. INPUT: the same fields as createDeepResearchReport — inputType and templateSlug, plus the source field for that inputType (VIEW → viewId, CREATOR → creatorId, CAMPAIGN → campaignId, BRAND → brandIds). OUTPUT: { deepResearchQuote: { inputType, templateSlug, affordable, holdCredits, estimateCredits, availableCredits } }. An invalid input is an error naming the field. REFUSALS: getDeepResearchQuote and createDeepResearchReport can be refused. Retrying does not help; tell the user why. DEEP_RESEARCH_NOT_AVAILABLE: the workspace's plan does not include Deep Research. NOT_AUTHORIZED: the user's workspace role cannot spend credits, or this connection lacks write access (the user can reconnect with write access). RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getDeepResearchQuote
PURPOSE: Read one Deep Research report: its progress while it runs, and once it has completed, the full report as Markdown plus its public share link. Poll this after createDeepResearchReport until running is false — reports take minutes; wait between polls. running follows the status Deep Research holds, so a report that stalls stays running true until Deep Research fails or cancels it: cap how long you poll (for example, give up once createdAt is hours old). INPUT: id (required: the report UUID from createDeepResearchReport or getDeepResearchReports). OUTPUT: { deepResearchReport: { id, status, running, phase, progressMessage, errorMessage, title, templateSlug, inputType, sourceId, sourceName, createdAt, completedAt, postsAnalyzed, shareUrl, markdown } | null }. markdown and shareUrl are null until status is COMPLETED; errorMessage says why a FAILED report failed. Returns { deepResearchReport: null } (NOT an error) when there is no such report in this workspace. REFUSALS: getDeepResearchQuote and createDeepResearchReport can be refused. Retrying does not help; tell the user why. DEEP_RESEARCH_NOT_AVAILABLE: the workspace's plan does not include Deep Research. NOT_AUTHORIZED: the user's workspace role cannot spend credits, or this connection lacks write access (the user can reconnect with write access). RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getDeepResearchReport
PURPOSE: List the Deep Research reports in the current workspace, newest first, whoever started them (the Archive app or the API). INPUT: status (optional: PENDING, FETCHING, PROCESSING, COMPLETED, FAILED or CANCELLED); first (optional page size 1–100, default 20); after (optional: pageInfo.endCursor of the previous page — keep `first` the same while paging). OUTPUT: { deepResearchReports: { nodes: [{ id, status, running, title, templateSlug, inputType, sourceName, createdAt, completedAt, shareUrl, ... }], pageInfo: { hasNextPage, endCursor }, totalCount } }. status is PENDING, FETCHING or PROCESSING (in flight) or COMPLETED, FAILED or CANCELLED (final). A report also reads PROCESSING when Deep Research left it paused in a deprecated state (running false) or has it in a step this list does not name separately; the PROCESSING filter matches neither. Poll on running, not status, to know whether to keep waiting. running follows the status Deep Research holds: a report that stalls in flight stays running true until Deep Research fails or cancels it, so cap how long you poll. inputType is VIEW, CREATOR, CAMPAIGN or BRAND. Read one report's Markdown with getDeepResearchReport. REFUSALS: getDeepResearchQuote and createDeepResearchReport can be refused. Retrying does not help; tell the user why. DEEP_RESEARCH_NOT_AVAILABLE: the workspace's plan does not include Deep Research. NOT_AUTHORIZED: the user's workspace role cannot spend credits, or this connection lacks write access (the user can reconnect with write access). RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getDeepResearchReports
PURPOSE: List the Deep Research report templates this workspace can run — the same list the Archive app offers. Start here: a report needs a template slug and a source type the template accepts. INPUT: inputType (optional: VIEW, CREATOR, CAMPAIGN or BRAND) — only templates that run on it. OUTPUT: { deepResearchTemplates: [{ slug, name, description, inputTypes, audienceComments, brandThreads }] }. audienceComments / brandThreads are NOT_SUPPORTED, OPTIONAL or REQUIRED. inputTypes lists only VIEW, CREATOR, CAMPAIGN and BRAND; a template is listed when it runs on at least one of them and its audienceComments / brandThreads are one of the values above. NEXT: getDeepResearchQuote with a slug, then createDeepResearchReport. REFUSALS: getDeepResearchQuote and createDeepResearchReport can be refused. Retrying does not help; tell the user why. DEEP_RESEARCH_NOT_AVAILABLE: the workspace's plan does not include Deep Research. NOT_AUTHORIZED: the user's workspace role cannot spend credits, or this connection lacks write access (the user can reconnect with write access). RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getDeepResearchTemplates
PURPOSE: Look up a single campaign by id in the current workspace, with its type, externalId, dates and roster size. INPUT: id (required string — the campaign UUID as returned by createCampaign or getCampaigns). OUTPUT: { campaign: { id, name, createdAt, campaignType, externalId, dateStart, dateEnd, tagNames, creatorsCount } | null }. campaignType is CREATOR_MONITORING or CONTENT_CAPTURE, or null for a campaign of a type the API does not expose (such a campaign cannot be changed with updateCampaign). externalId is null for a campaign created in the Archive app. dateStart / dateEnd are UTC, null when the campaign has none. tagNames is the stored settings.creatorMonitoring.tagNames of a CREATOR_MONITORING campaign (empty captures every post), null for another type. creatorsCount counts the creators on the roster now; creators added with updateCampaign join it once their background import resolves them. Returns { campaign: null } (NOT an error) when no campaign with that id exists in the current workspace: an unknown id, an id owned by another workspace, or an internal workflow row that getCampaigns does not list either — the same observable, on purpose. Use getCampaigns to list campaigns; createCampaign / updateCampaign to create or change one. Read a campaign's posts with searchItems using filter.campaignsIds. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getCampaign
PURPOSE: Look up a single Collection (saved tag set) by id in the current workspace. INPUT: id (required string — a Collection id as returned by getCollections / createCollection for this workspace). Ids differ between workspaces depending on how each one stores Collections, so always resolve the id through getCollections rather than constructing or reusing one. OUTPUT: { collection: { id, name, customAttributeOptionId, itemCount, group: { id, name } | null } | null }. Returns { collection: null } (NOT an error) when no Collection with that id exists in the current workspace (unknown id, or id owned by another workspace — same observable, on purpose). `customAttributeOptionId` is the Collection's option id in the ITEM "collections" custom attribute — the value a "collections" custom-attribute condition takes, different from `id`; null where the workspace uses the older Collection storage. `itemCount` is the number of items tagged with the Collection in this workspace. `group` is the view group the Collection belongs to (set with moveCollectionToGroup), or null when ungrouped — always null where the workspace uses the older Collection storage. In workspaces whose Collections are preset-backed you can pair the returned `id` with searchItems(presetId:) to fetch the items tagged with the Collection; that pairing does not apply where the workspace uses the older storage. Creating/renaming/deleting a Collection (createCollection / updateCollection / deleteCollection) is available only in workspaces whose Collections use the standard storage — where the workspace uses the older storage those calls return a userError and change nothing. Tagging items with addItemToCollections / removeItemFromCollections works in both. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getCollection
PURPOSE: Look up a single Competitor Insights brand by id in the current workspace, with aggregate metrics over a period/date window. Also resolves the workspace's own brand by its stable id (isOwnBrand: true). INPUT: id (required string, the brand's Archive id), optional period ("WEEK"|"MONTH", default "MONTH") and date (ISO date, defaults to the latest complete month or week; a later date is moved back to it). OUTPUT: { id, name, displayName, isOwnBrand, earnedMediaValue, engagementsTotal, impressions, reach, postsCount, influencersCount, ownMetricsStatus, ownMetricsHasData } on success. displayName is the name the Archive app shows: the brand name for competitors, the linked own brand's name for the own entry ("You" when none is linked). For the own entry, ownMetricsStatus is AVAILABLE (null metrics then mean no data in the window) or UNAVAILABLE (retry later); it is null for competitors. ownMetricsHasData is true when AVAILABLE metrics carry data, false when AVAILABLE but the window has no own-brand data (the null metrics are missing, not zero), and null for competitors or when UNAVAILABLE. Returns an isError tool result with the text "Competitor brand not found" when no brand with that id is tracked in the current workspace (unknown id, or known id tracked only by another workspace — same observable, on purpose). WARNINGS: If the metrics store is temporarily unavailable, brand identity data is still returned with null metrics and a `warnings` array containing the message below. An own-brand result has ownMetricsStatus "UNAVAILABLE". Back off for minutes before retrying; do not immediately repeat the call. "Competitor metrics are temporarily unavailable. Retry later." RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getCompetitorBrand
PURPOSE: Look up a single saved Content View by id in the current workspace. INPUT: id (required string, the content view's Archive id / FilterPreset UUID). OUTPUT: { contentView: { id, name, filters, customAttributeConditions, sort, showReportingStats, group } | null }. Returns { contentView: null } (NOT an error) when no media_deck view with that id exists in the current workspace (unknown id, id owned by another workspace, or a view hidden in the Archive app — same observable, on purpose). Pair the returned `id` with searchItems(presetId:) to fetch the items belonging to the view. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getContentView
PURPOSE: Look up a single creator (influencer) by id in the current workspace. INPUT: id (required string, the creator's Archive id). OUTPUT: { id, customAttributes } on success. Returns an isError tool result with the text "Creator not found" when no creator with that id exists in the current workspace (unknown id, or known id owned by another workspace — same observable, on purpose). RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getCreator
PURPOSE: Look up a single saved Creator View by id in the current workspace. INPUT: id (required string — the Creator View's Archive id / FilterPreset UUID, as returned by getCreatorViews). OUTPUT: { creatorView: { id, name, filters, customAttributeConditions, sort, showReportingStats, group } | null }. Returns { creatorView: null } (NOT an error) when no creator view with that id exists in the current workspace (unknown id, id owned by another workspace, or a view hidden in the Archive app — same observable, on purpose). Pair the returned `id` with searchCreators(presetId:) to fetch the view's creators. To create/update/delete use createCreatorView / updateCreatorView / deleteCreatorView. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getCreatorView
PURPOSE: List custom attribute schemas for the current workspace, used both to INTERPRET values in the `customAttributes` JSON field on items/creators AND to BUILD `customAttributeConditions` filters for searchItems / searchCreators. INPUT: entity (required: "ITEM" or "CREATOR"). ITEM → schemas attached to items (`shop_item`); CREATOR → schemas attached to creators. OUTPUT: { items: [{ key, name, type, aiGenerated, options: [{ id, name }] }] } - `key` matches a top-level field inside the entity's customAttributes hash (and is the `field` in a filter condition). - `type` is the upper-case attribute type (TEXT, SINGLE_SELECT_V2, MULTIPLE_SELECT_V2, etc.) — pass it as `type` in a filter condition. - `aiGenerated` is true when the attribute's value is produced by an AI Filter; searchItems returns the model's explanation for those keys in each item's `aiFilterReasons`. - `options` is `[]` for non-select schemas; for select-type schemas each option's `id` is what appears as the value (or array element) in customAttributes and is the `value` you pass when filtering on that field. CUSTOM ATTRIBUTE FILTERS (customAttributeConditions): Filter by the workspace's user-defined custom fields. An array of { field, operator, type, value } objects; multiple entries are AND-ed together. Step 1 - discover fields: call getCustomAttributeSchemas(entity: ITEM | CREATOR). Each schema returns `key` (use as `field`), `type` (use as `type`), and `options: [{ id, name }]` for select fields (use an option `id` as `value`). Step 2 - build each condition: - field : the schema `key` (e.g. "sentiment", "links"). - type : the schema `type`, UPPERCASE - one of TEXT, EMAIL, PHONE, URL, NUMBER, BOOLEAN, DATE, DATETIME, SINGLE_SELECT_V2, SINGLE_SELECT_V3, MULTIPLE_SELECT, MULTIPLE_SELECT_V2, TEXT_LIST, NUMBER_LIST, DATE_LIST, DATETIME_LIST, BOOLEAN_LIST. - operator : UPPERCASE; the valid set depends on the field's type group (see below). - value : depends on `type`: * TEXT / EMAIL / PHONE / URL -> a string. * SINGLE_SELECT_V2 / SINGLE_SELECT_V3 -> option `id` (UUID), or with no options in the schema (e.g. `sentiment`) the stored string ("Positive"). * NUMBER -> a number; BETWEEN takes { from, to }. * DATE / DATETIME -> ISO-8601 string; BETWEEN takes { from, to }. * BOOLEAN -> true / false. * MULTIPLE_SELECT / MULTIPLE_SELECT_V2 -> array of at least one option `id`. * TEXT_LIST / NUMBER_LIST / DATE_LIST / ... -> array of values. * IS_EMPTY / IS_NOT_EMPTY -> value is ignored; pass null. Operators by type group (an operator outside its group, or a SHIPPING_ADDRESS-typed condition, is rejected with an error naming the field): - Text & single-select (TEXT, EMAIL, PHONE, URL, SINGLE_SELECT_V2, SINGLE_SELECT_V3): IS, IS_NOT, CONTAINS, DOES_NOT_CONTAIN, STARTS_WITH, ENDS_WITH, IS_EMPTY, IS_NOT_EMPTY. (IS / IS_NOT are exact match on the select value described above.) - Number (NUMBER): EQUAL, NOT_EQUAL, MORE_THAN, MORE_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, BETWEEN, IS_EMPTY, IS_NOT_EMPTY. - Date (DATE, DATETIME): EQUAL, NOT_EQUAL, MORE_THAN, MORE_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL, BETWEEN, IS_EMPTY, IS_NOT_EMPTY, IS_RELATIVE_TO_TODAY. IS_RELATIVE_TO_TODAY value: { relation: "past"|"this"|"next", period: "day"|"week"|"month"|"year" } with an optional whole-number offset (at most 100 years) and an optional IANA time zone "tz". - Boolean (BOOLEAN): IS (value true / false). - Multi-value (MULTIPLE_SELECT, MULTIPLE_SELECT_V2, and every *_LIST type): CONTAINS (matches ANY of the values, OR), CONTAINS_ALL (must contain ALL, AND), DOES_NOT_CONTAIN, IS_EMPTY, IS_NOT_EMPTY. NOTE: post_summary and shipping_address are stored but NOT indexed: positive operators match NOTHING, negated ones (IS_NOT, DOES_NOT_CONTAIN, IS_EMPTY) match EVERY record — read them from each item's `customAttributes` instead. NOTE: on items, `post_date` is the post time: DATE/DATETIME with a plain date (whole UTC day), datetime, { from, to } or IS_RELATIVE_TO_TODAY; NOT_EQUAL, IS_EMPTY and "$now" are rejected. `labels` takes the multi-value operators with label NAMES as values (its schema lists no options), matched CASE-SENSITIVELY, unlike the label tools. A blank `field` or an empty option list is rejected, as is a string value starting with "$" other than "$now". At most 20 conditions; a string value at most 256 characters; at most 50 values per list (500 option ids for a multi-select). Details: README §5.3. Examples: [{ "field": "sentiment", "operator": "IS", "type": "SINGLE_SELECT_V2", "value": "Positive" }] [{ "field": "links", "operator": "CONTAINS", "type": "TEXT_LIST", "value": ["https://example.com/promo"] }] [{ "field": "lead_score", "operator": "BETWEEN", "type": "NUMBER", "value": { "from": 10, "to": 100 } }] [{ "field": "notes", "operator": "IS_NOT_EMPTY", "type": "TEXT", "value": null }] RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getCustomAttributeSchemas
PURPOSE: Paginated history of engagement metric snapshots for a single item, newest first. INPUT: itemId (required string). Optional cursor, limit (default 20, max 100), and filter { capturedAt: { from, to } } (ISO-8601 date-time bounds, UTC only — offsets other than Z/+00:00/-00:00 are rejected; both bounds are optional). An unknown or foreign itemId returns an isError result with the coded text "Item not found". OUTPUT: { items: [...], pageInfo: { hasNextPage, endCursor }, totalCount }. Each item node is { at, likes, comments, views, shares, impressions, earnedMediaValue, followers, linearViralityScore }. Metric values in nodes may be null when data has not been captured. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getEngagementHistory
PURPOSE: Retrieve media contents (images / videos) for shop items OR for tracked Competitor Insights items in the current workspace. INPUT: exactly one of itemIds (Item / shop-item UUIDs) OR competitorBrandItemIds (CompetitorBrandItem UUIDs from getCompetitorBrandItems). Each is an array of 1..100 string IDs. Passing both, or neither, returns an isError result. OUTPUT: { items: [...] } — one node per media-content row. Each node carries id, mediaItemId, type, fileUrl, thumbnailUrl, width, height, deleted; videos additionally carry videoDuration. NOTE: fileUrl and thumbnailUrl are raw CDN URLs (unsigned); YouTube nodes always have fileUrl: null and thumbnailUrl may be null. Unknown, cross-workspace, or non-entitled competitor item IDs yield zero rows (not an error). RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getMediaContents
PURPOSE: Look up a single async operation by id in the current workspace — poll its status and progress (e.g. after refetchEngagementBulk). INPUT: id (required string, the operation's Archive id). OUTPUT: { id, status, operationType, total, processed, succeededCount, failedCount, pendingCount, succeededItemIds, failedItemIds, pendingItemIds, itemIdsTruncated, createdAt, completedAt, failedRecordsCsvUrl, successfulRecordsCsvUrl, importSource } on success (completedAt is null until the operation finishes). The three counts are always exact. Each item-id list holds at most 1000 ids: when itemIdsTruncated is true some ids were omitted — use the counts for exact sizes and page through getOperationRecords for the remaining ids; do not report a partial list as the whole outcome. For a creator import (operationType oneschema_creator_import) the three lists are always empty and itemIdsTruncated is false: its records are uploaded rows, not items — page through getOperationRecords for them. A label operation (delete_label, rename_label, merge_labels) keeps no per-item records: its succeededCount / failedCount / pendingCount are always 0 and its lists empty, even when COMPLETED, so they do not add up to processed. Read status, total and processed for its progress. Counts and id lists are separate reads: while status is QUEUED or PROCESSING they are a moving snapshot and may briefly disagree as records finish; on a terminal status records no longer change, so the response is exact and self-consistent. status values: QUEUED (not yet started), PROCESSING (in progress), COMPLETED (all items succeeded — terminal), PARTIAL (finished with some failures — terminal), FAILED (all items failed — terminal). Returns an isError tool result with the text "Operation not found" when no operation with that id exists in the current workspace (unknown id, or known id owned by another workspace — same observable, on purpose). CREATOR IMPORT: this is where to poll a creator import (operationType oneschema_creator_import) until its status is terminal. failedRecordsCsvUrl and successfulRecordsCsvUrl are download links valid for 1 hour, written shortly after a PARTIAL or FAILED import finishes, null otherwise; importSource is CSV_UPLOAD or PUBLIC_API. All three are null for every other operation type. Page through getOperationRecords for each row's handles, creatorId and error. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getOperation
PURPOSE: Page through the per-item records of one operation, newest first — the follow-up to getOperation when itemIdsTruncated is true, and the way to enumerate an operation's items with their per-item status. INPUT: operationId (required string), optional status filter (SUCCEEDED | FAILED | PENDING — PENDING covers not-started, in-progress and retrying records), optional cursor, limit (default 100, max 1000). OUTPUT: { records: [...], pageInfo: { hasNextPage, endCursor }, totalCount }. Each record is { itemId, status }; itemId is a documented input to getMediaContents / getTranscriptions. totalCount is the exact number of records matching the filter. Returns an isError tool result with the text "Operation not found" when no operation with that id exists in the current workspace, and "Invalid cursor" for a cursor this connection did not issue. CREATOR IMPORT: each record also carries { handles, creatorId, errorCode, errorMessage }, filled for the rows of a creator import (operationType oneschema_creator_import) and null for every other operation type. On those rows itemId is the row key within the import (import_0, ...), not an item id. handles lists the row's [{ provider, handle }] (null for rows stored in a format it cannot read); creatorId is the creator a SUCCEEDED row created or updated, an input to getCreator; errorCode and errorMessage say why a FAILED row failed, the message in words fit to show a person. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getOperationRecords
PURPOSE: Look up ONE social profile (influencer) in the current workspace. For MANY profiles do NOT loop this per id — call getSocialProfiles once to list/filter a whole page of profiles in a single call (the batch path). INPUT: provide EXACTLY ONE of: - id (the social profile's Archive id), OR - accountName + provider (provider is one of instagram, tiktok, youtube). Optional fallback (default false): when true and the profile is not archived locally, fetch it live from the social platform (slower). Passing both id and accountName/provider, or accountName without provider, or neither, returns an isError result. OUTPUT: { socialProfile: { id, provider, originalUrl, accountName, avatar, private, verified, followers, following, fullName, email, phoneNumbers, proAccount, creator { id } } } on success, or { socialProfile: null } when no profile matches in the current workspace (workspace-scoped lookup; profiles archived only in other workspaces are treated as misses and return null, not an error). With fallback: true a miss may instead return isError: true with one of: - "Upstream social-platform service is temporarily unavailable. Please retry." (UPSTREAM_UNAVAILABLE code in extensions — safe to retry); - a PROVIDER_ERROR message from the platform (e.g. rate-limited); - "User not found on <provider>." (the account does not exist on the platform). RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getSocialProfile
PURPOSE: Look up a single saved Social Profile view by id in the current workspace. INPUT: id (required string — the Social Profile view's Archive id / FilterPreset UUID, as returned by getSocialProfileViews). OUTPUT: { socialProfileView: { id, name, filters, customAttributeConditions, sort, showReportingStats, group } | null }. Returns { socialProfileView: null } (NOT an error) when no social-profiles view with that id exists in the current workspace (unknown id, id owned by another workspace, or a view hidden in the Archive app — same observable, on purpose). Pair the returned `id` with getSocialProfiles(presetId:) to fetch the view's social profiles. To create/update/delete use createSocialProfileView / updateSocialProfileView / deleteSocialProfileView. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getSocialProfileView
PURPOSE: Fetch transcriptions for the media contents of one or more items in the current workspace. INPUT: itemIds (required) — an array of 1..1000 Item UUIDs. OUTPUT: { items: [...] } — one node per media content that has a non-empty transcript across the requested items. Each node carries mediaContentId and transcript. Items with no (or only empty) transcriptions yield no rows. NOTE: v0 exposes only the itemIds (Elasticsearch) path; the deferred mediaContentIds (DB) path is not available. NOTE: rate-limit cost scales with the number of itemIds but is capped at 100 — a request with more than 100 ids (up to the 1000 max) is charged as 100. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getTranscriptions
PURPOSE: Look up a single user-created view group by id in the current workspace, including its member views. INPUT: id (required string — the ViewGroup UUID as returned by getViewGroups / createViewGroup). OUTPUT: { viewGroup: { id, name, contentViews: [{ id, name }], socialProfileViews: [{ id, name }], creatorViews: [{ id, name }], collections: [{ id, name }] } | null }. Member views carry id and name only — fetch a member's configuration (filters, sort, …) with getContentView / getSocialProfileView / getCreatorView / getCollection. `contentViews`, `socialProfileViews`, `creatorViews`, and `collections` enumerate the group's members in their within-group position order (ties break on id for a stable order). CAMPAIGN Creator Views are never group members (they are campaign-scoped, not workspace-scoped) — workspace Creator Views ARE groupable and appear in `creatorViews`. Returns { viewGroup: null } (NOT an error) when no group with that id exists in the current workspace (unknown id, or id owned by another workspace — same observable, on purpose). To create/rename/delete a group use createViewGroup / updateViewGroup / deleteViewGroup; to move a view into/out of a group use moveContentViewToGroup / moveSocialProfileViewToGroup / moveCreatorViewToGroup / moveCollectionToGroup. reorderViewsInGroup rewrites member positions — read the full member list from this tool first, since a reorder that omits members leaves their positions unchanged. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getViewGroup
PURPOSE: Get the workspace's outbound-webhook caps and its current usage, so you can check headroom before createWebhookSubscription / updateWebhookSubscription instead of hitting a limit userError. INPUT: none (beyond the workspace selector). OUTPUT: { limits: { tier, maxSubscriptions, usedSubscriptions, maxViewsPerSubscription, metadataMaxBytes, capsSource } } usedSubscriptions counts subscriptions in any status. capsSource is the highest override level that replaced at least one cap: "workspace_override", "org_override", or "plan" (both caps are tier defaults). Each cap resolves on its own, so "workspace_override" does not mean both caps came from the workspace. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getWebhookLimits
PURPOSE: Get a workspace — its tracked hashtags/mentions/keywords and connected social integrations — in one call. The workspace is selected by the optional `workspaceId` argument (falling back to the `WORKSPACE-ID` header, or your sole workspace when you can access exactly one). Call getWorkspaces first to discover the ids you can access. INPUT: optional workspaceId — the workspace UUID (from getWorkspaces) or the numeric workspace id shown in the Archive app. OUTPUT: { workspace: { id, name, hashtags: [...], mentions: [...], keywords: [...], integrations: [...] } }. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getWorkspace
PURPOSE: List campaigns for the current workspace, newest first. INPUT: optional cursor, limit (default 20, max 100). No filter, no sorting (results are always newest first). OUTPUT: { campaigns: [...], pageInfo: { hasNextPage, endCursor }, totalCount }. Each campaign node is { id, name, createdAt }. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getCampaigns
PURPOSE: List Collections (saved tag sets) for the current workspace, in the workspace's saved display order. INPUT: none (beyond the workspace selector). OUTPUT: { items: [{ id, name, customAttributeOptionId, itemCount, group: { id, name } | null }] } `id` is the id this workspace accepts for addItemToCollections / removeItemFromCollections and for getCollection(id:). ALWAYS take Collection ids from this tool — never construct them, cache them, or reuse one across workspaces. Some workspaces store Collections in an older format and their ids look different; the ids listed here are always the ones that workspace accepts. `customAttributeOptionId` is the Collection's option id in the ITEM "collections" custom attribute (getCustomAttributeSchemas entity ITEM). It differs from `id`: use it as the value of a "collections" custom-attribute condition and to match an item's customAttributes.collections. Null where the workspace uses the older Collection storage. `itemCount` is the number of items in this workspace tagged with the Collection. `group` is the view group the Collection belongs to (set with moveCollectionToGroup), or null when ungrouped — always null where the workspace uses the older Collection storage. In workspaces whose Collections are preset-backed you can pair a Collection's `id` with searchItems(presetId:) to fetch the items tagged with that Collection; that pairing does not apply where the workspace uses the older storage. Creating/renaming/deleting a Collection (createCollection / updateCollection / deleteCollection) is available only in workspaces whose Collections use the standard storage — where the workspace uses the older storage those calls return a userError and change nothing. Tagging items with addItemToCollections / removeItemFromCollections works in both. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getCollections
PURPOSE: Paginate posts attributed to a single tracked Competitor Insights brand within a required `takenAt` time window. INPUT: brandId (required string, the brand's Archive id — not an ISO-8601 date-time); takenAtFrom and takenAtTo (required ISO-8601 date-time, UTC only — offsets other than Z/+00:00/-00:00 are rejected); optional sorting ({ sortKey: TAKEN_AT|EARNED_MEDIA_VALUE, sortOrder: ASC|DESC }, default TAKEN_AT DESC), limit (default 20, max 100), cursor, responseFormat (concise | detailed, default detailed — see OUTPUT). An unknown or foreign brandId returns an empty connection (not an error). EARNED_MEDIA_VALUE ranks posts as one ordering across the whole window. OUTPUT: { items: [...], pageInfo: { hasNextPage, endCursor }, totalCount }. responseFormat "detailed" (default) returns the full per-node shape; "concise" trims each node to id, takenAt, provider, type, originalUrl, caption, socialProfile { id accountName }, and currentEngagement — for listing / filtering / ranking. NOTE: a month's posts become available on day 9 of the following month — the current month is never queryable. The cursor is positional — pass pageInfo.endCursor back with the same brandId, takenAtFrom/takenAtTo, and sorting; responseFormat may change freely between pages. A malformed cursor (including one minted before the ClickHouse cutover) is rejected with "Invalid cursor", and pagination depth is capped at 10,000 posts per query — narrow the takenAt window to go deeper. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getCompetitorBrandItems
PURPOSE: List Competitor Insights brands tracked for the current workspace, newest first, with aggregate metrics over a period/date window, so self-vs-competitor Share of Voice is computable in one call. INPUT: optional cursor, limit (default 20, max 100), period ("WEEK"|"MONTH", default "MONTH"), date (ISO date, defaults to the latest complete month or week; a later date is moved back to it). No filter, no sorting (results are always newest first). OUTPUT: { brands: [...], pageInfo: { hasNextPage, endCursor }, totalCount }. Each brand node is { id, name, displayName, isOwnBrand, earnedMediaValue, engagementsTotal, impressions, reach, postsCount, influencersCount, ownMetricsStatus, ownMetricsHasData }. The workspace's own brand is returned as one additional pinned node on the first page (isOwnBrand: true, name "You"; displayName is the linked own brand's name as the Archive app shows it, or "You" when none is linked), in addition to up to `limit` competitor brands; totalCount counts competitor brands only and excludes the own entry. For the own entry, ownMetricsStatus is AVAILABLE (null metrics then mean no data in the window) or UNAVAILABLE (retry later); it is null for competitors. ownMetricsHasData is true when AVAILABLE metrics carry data, false when AVAILABLE but the window has no own-brand data (the null metrics are missing, not zero), and null for competitors or when UNAVAILABLE. WARNINGS: If the metrics store is temporarily unavailable, the roster is still returned with null metrics, ownMetricsStatus "UNAVAILABLE", and a `warnings` array containing the message below. Back off for minutes before retrying; do not immediately repeat the call. "Competitor metrics are temporarily unavailable. Retry later." RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getCompetitorBrands
PURPOSE: List saved Content Views for the current workspace, ordered most-recently-updated first. INPUT: optional groupId (filters to one group; omitted/null returns all Content Views). Views hidden in the Archive app are never returned. An unknown or foreign groupId returns an empty list (not an error). OUTPUT: { items: [{ id, name, filters, customAttributeConditions, sort, showReportingStats, group }] } Pair an item's `id` with searchItems(presetId:) to fetch the items belonging to a view. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getContentViews
PURPOSE: List saved Creator Views for the current workspace, ordered most-recently-updated first. INPUT: optional groupId (filters to one group; omitted/null returns all creator views). Views hidden in the Archive app are never returned. An unknown or foreign groupId returns an empty list (not an error). OUTPUT: { items: [{ id, name, filters, customAttributeConditions, sort, showReportingStats, group }] } Pair an item's `id` with searchCreators(presetId:) to fetch the view's creators. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getCreatorViews
PURPOSE: DEPRECATED — prefer the typed view tools getContentViews (accessor MEDIA_DECK) and getCollections (accessor COLLECTIONS); their ids work the same way as a presetId input. This tool still lists saved filter presets for the current workspace (no removal window announced), but new integrations should not adopt it. Use the returned id as `presetId:` when calling items(...) to scope a search to the preset's saved filter set. INPUT: none (no arguments). OUTPUT: { items: [{ id, name, accessor }, ...] }. `accessor` is one of "MEDIA_DECK" or "COLLECTIONS" (the resolver only exposes those two; presets with other accessors or `visible: false` are filtered out). Ordered by the workspace's default group position, then by creation time. Empty workspaces return `{ items: [] }`. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getFilterPresets
PURPOSE: List the creator labels of the current workspace, alphabetically by name (case-insensitive). Symbols and emoji follow the database collation, not code-point order (e.g. "zz-🎉" sorts before "zz-alpha"). INPUT: none (beyond the workspace selector). OUTPUT: { items: [{ name, deleting }] } `name` is the label's identity; labels have no id in this API. Pass a name back exactly as returned. The label tools match names ignoring case and surrounding whitespace; the `labels` customAttributeConditions filter on searchCreators matches the exact, case-sensitive name. A label with `deleting: true` is being removed; do not assign it, and do not recreate it until it disappears from getLabels. Capped at 1000 entries and not paginated. VERIFY-AFTER-WRITE TARGET: call this after any label change in this workspace, including labels that importCreators registers, and confirm the name is present (or gone). RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getLabels
PURPOSE: List operations for the current workspace, newest first. Only `refetch_engagement`, creator-import, label operations (delete_label, rename_label, merge_labels) and creator label bulk operations are listed here; an operation id visible via getOperation may be absent from this list if it is of another internal type. A label operation's record counts are always 0 — read status, total and processed. INPUT: optional cursor, limit (default 20, max 100). No filter, no sorting (results are always newest first). OUTPUT: { operations: [...], pageInfo: { hasNextPage, endCursor }, totalCount }. Each operation node is { id, status, operationType, total, createdAt }. status values: QUEUED (not yet started), PROCESSING (in progress), COMPLETED (all items succeeded — terminal), PARTIAL (finished with some failures — terminal), FAILED (all items failed — terminal). CREATOR IMPORT: the list also holds the workspace's creator imports (operationType oneschema_creator_import). Poll an import with getOperation and read its rows with getOperationRecords. LABEL BULK: the list also holds creator label bulk operations (operationType update_custom_attributes for bulkAddLabelsToCreators, remove_custom_attributes for bulkRemoveLabelsFromCreators, and the same bulk edits made in the Archive app); those carry one record per creator — read them with getOperationRecords. No other custom-attribute edit is listed. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getOperations
PURPOSE: List saved Social Profile views for the current workspace, ordered most-recently-updated first. INPUT: optional groupId (filters to one group; omitted/null returns all social-profile views). Views hidden in the Archive app are never returned. An unknown or foreign groupId returns an empty list (not an error). OUTPUT: { items: [{ id, name, filters, customAttributeConditions, sort, showReportingStats, group }] } Pair an item's `id` with getSocialProfiles(presetId:) to fetch the view's social profiles. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getSocialProfileViews
PURPOSE: List social profiles (Instagram / TikTok / YouTube accounts) tracked for the current workspace, profiles with the most recent content first. This is the batch / multi-profile path — reach for it instead of calling getSocialProfile once per id when you need more than one profile. INPUT (all optional): - filter (object): a SocialProfileFilterInput. Fields: * platform: one of INSTAGRAM, TIKTOK, YOUTUBE, INTERNAL. - presetId (string): a saved Social Profile View id (from getSocialProfileViews / getSocialProfileView). When set, the view's stored customAttributeConditions and sort drive the results and the inline filter argument is IGNORED (the view's `filters` blob is never applied on read). A non-Social-Profile-View id returns a coded error with extensions.code = "WRONG_VIEW_TYPE"; an unknown or foreign id returns extensions.code = "NOT_FOUND" (cross-workspace ids collapse to NOT_FOUND — no enumeration leak). - cursor (string), limit (integer, default 20, max 100). Cursor note: pass pageInfo.endCursor only — per-node edge cursors are not valid here. - responseFormat (string): "concise" or "detailed" (default) — see OUTPUT. No sorting argument — results are most-recent-content first (a preset's stored sort overrides this). OUTPUT: { socialProfiles: [{ id, provider, originalUrl, accountName, avatar, private, verified, followers, following, fullName, email, phoneNumbers, proAccount, creator { id } }], pageInfo: { hasNextPage, endCursor }, totalCount } responseFormat "detailed" (default) returns the node shape above; "concise" returns { id, accountName, provider, followers, verified } per node — for listing / filtering / ranking. Use "detailed" when contact fields (email, phoneNumbers, fullName) or the full profile shape are needed. NOTE: no inline custom-attribute filter exists on this query — to narrow by custom attributes, create/point at a Social Profile View with customAttributeConditions (createSocialProfileView) and pass its id as presetId. RUNTIME NOTES: - Rate limiting: a weighted per-workspace rate limit is enforced on every call. A throttled call returns isError text: "Rate limit exceeded. Retry after N seconds." - Argument validation: arguments failing schema validation return isError text like "Invalid argument '$.<path>': <reason>". - Unexpected failures: any other error returns isError text "Tool execution failed".
getSocialProfiles
Archive ChatGPT Plugin FAQ
How the directory, categories and Discoverability Score work.
Read the methodologyHow do I improve Archive's ChatGPT Plugin discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are Archive alternatives on ChatGPT?
As of 2026-10-28, Archive competes with Cheerful, Collabed, Heepsy Influencer Search, InboundOS, Influee, Influencer Hero, Influencers Club, Influship and 6 more in ChatGPT Influencer & Creator Discovery, ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.