Skai (Kenshoo) API

Skai's REST API for programmatic access to advertising data and campaign management across search, social and retail-media publishers. Reporting is the primary surface — synchronous for small pulls, asynchronous analysis reports for anything larger — alongside Bulk Update (one file, millions of rows, hundreds of attributes) for scaled changes, typed CRUD for campaigns/ad groups/ads/portfolios/product groups, a separate /api/v2 branch for Meta entities, custom columns, incrementality data sources and budget pacing. Authentication is a bearer JWT obtained by exchanging a permanent refresh token; requests are scoped by a `ks` account identifier. Rate limited to 60 requests/minute and 2,000/hour per user.

OpenAPI Specification

skai-kenshoo-api-openapi.yml Raw ↑
openapi: "3.0.0"
info:
  title: "Skai API"
  description: "# Overview\nSkai APIs provide programmatic access to advertising data\
    \ and campaign management across Search, Social, and Retail Media publishers.\n\
    \n## Choosing the Right API\n\n| What you want to do | API to use | Scale | Notes\
    \ |\n|---|---|---|---|\n| Pull performance data, metrics, or any reportable field\
    \ | [Reporting](#tag/Synchronous-Reports) or [Async Reporting](#tag/Asynchronous-Reports)\
    \ | Unlimited | Primary data access API — the main Skai value-prop |\n| Discover\
    \ what columns and metrics are available | [Available Columns](#operation/getAvailableColumns)\
    \ | — | Full list of reportable fields per entity type |\n| Create or update campaigns,\
    \ keywords, bids, budgets, targeting, and more — at scale | [Bulk Update (One\
    \ File)](#tag/Bulk-Update) | Millions of rows | Supports Skai's main entity types\
    \ and hundreds of attributes; all publishers except Meta |\n| Create/update a\
    \ small number of campaigns or ad groups (common attributes only) | [Campaigns](#tag/Campaigns)\
    \ / [Ad Groups](#tag/Ad-Groups) / [Ads](#tag/Ads) | Thousands | Limited attribute\
    \ set — use Bulk Update for full control |\n| Manage Meta (Facebook/Instagram)\
    \ entities | [Meta Campaigns](#tag/Meta-Campaigns) / [Meta Ad Groups](#tag/Meta-Ad-Groups)\
    \ / [Meta Ads](#tag/Meta-Ads) | Thousands | Meta-specific tag and attribution\
    \ management |\n| Use Skai from an AI coding assistant (Claude, Cursor, ChatGPT,\
    \ Windsurf) | [MCP Integration](#tag/MCP) | — | Full reporting access via natural\
    \ language |\n\nSkai APIs are RESTful and language agnostic. Authentication uses\
    \ Bearer tokens over HTTPS.\n\n## What Data Can I Access?\n\nSkai aggregates advertising\
    \ data across three publisher categories:\n\n| Publisher category | Examples |\n\
    |---|---|\n| **Search** | Google Ads, Microsoft Ads, Yahoo Japan, Baidu, and others\
    \ |\n| **Social (excl. Meta)** | Pinterest, Snapchat, TikTok, LinkedIn, Reddit,\
    \ and others |\n| **Social (Meta)** | Facebook, Instagram |\n| **Retail Media**\
    \ | Amazon Ads, Walmart, Instacart, Kroger, Target, and 100+ others |\n\n**Reportable\
    \ entity types:**\n\n| Entity | Description | Publishers |\n|---|---|---|\n| `CAMPAIGN`\
    \ | Campaign-level data | All |\n| `ADGROUP` | Ad group / ad set level | All |\n\
    | `KEYWORD` | Keyword-level performance and settings | Search, Retail Media |\n\
    | `AD` | Individual ad creatives | All |\n| `PRODUCT_ASSET` | Product-level data\
    \ for shopping and retail media (called \"Products\" in the Skai UI) | Retail\
    \ Media, Search Shopping |\n| `PRODUCT_TARGETING` | Product targeting entities\
    \ — ASINs, categories, and product attributes | Retail Media |\n| `PORTFOLIO`\
    \ | Portfolio-level budget aggregations and pacing | All |\n\n**Available metric\
    \ categories per entity:**\n\n- **Performance** — Impressions, Clicks, Cost, Conversions,\
    \ Revenue, ROAS, CTR, CPC, and more\n- **Attributes** — Names, statuses, budgets,\
    \ bids, targeting settings, and publisher-specific fields\n- **Account-configured**\
    \ — Dimensions (custom tagging labels), Conversion events (publisher, pixel, and\
    \ 3rd-party), Custom Metrics (formula-based calculations your team defines)\n\n\
    Use [Available Columns](#operation/getAvailableColumns) to see the complete column\
    \ list for any entity — including full descriptions and types. A static reference\
    \ is embedded in that endpoint's documentation.\n\n\n## Authentication\nThe Skai\
    \ API uses the Bearer authentication scheme.\nThe first step is to generate a\
    \ *refresh token* (once), which you can then exchange for a temporary *access\
    \ token*, programmatically, before making an API call.\n\n> Note: The user you\
    \ use to generate your *refresh token* will determine the token's permissions.\
    \ API access is allowed for users with Standard role or higher.\nIt is recommended\
    \ that you create and use a specialized user for your API requests.\n\n\n####\
    \ Step 1: Get a Refresh Token\nYou only need to do this once, for each API user\
    \ you plan to use. \n\nLog into [this page](https://login.kenshoo.com/api/dev/refresh-token)\
    \ in order to get your *refresh token* and *client ID*. The user you log in with\
    \ will be the user accessing the API. \nPlease store your refresh token in a secure\
    \ place. While it is not possible to recover a refresh token, you can generate\
    \ a new one. The refresh token does not expire.\n\n\n#### Step 2: Generating an\
    \ Access Token\nBefore making API calls, your code uses the permanent *refresh\
    \ token* to generate a temporary *access token*.\n\nMake a call to /api/v1/token\
    \ (as shown below) with your *refresh token* and *client ID* to generate an *access\
    \ token*:\n\n    curl -X POST -d \"refresh_token=<YourToken>&client_id=<Your Client\
    \ Id>\" \\\n    https://services.kenshoo.com/api/v1/token\n\nNote: the client_id\
    \ and refresh token should be sent in the POST request body, as the refresh token\
    \ is confidential and should not be sent as url param.\nthe API will reject refresh\
    \ tokens sent in url params.\n\nGet token for specific agency context:\nIn case\
    \ your API user is assigned to multi accounts (agencies), you should explicitly\
    \ specify in the get access-token request which agency context you would like\
    \ to receive the token for.\nJust add to the request mentioned above another form\
    \ param called *agency_id*, and pass the relevant agency ID like this:\n    \n\
    \    curl -X POST -d \"refresh_token=<YourToken>&client_id=<Your Client Id>&agency_id=<Your\
    \ Agency Id>\" \\\n    https://services.kenshoo.com/api/v1/token\n\nToken expiration:\n\
    Please check for token expiration before sending another API request , you have\
    \ 2 options:\n\n1. Call the API and get 401 status code indicating authentication\
    \ failed.\n2. Consider the *expires_in* field of the token to issue a new access\
    \ token.\n\nThe response will return a JSON containing the token and time for\
    \ expiration in seconds.\nIt is recommended to use the token expiration time and\
    \ reuse tokens while they are still valid, to prevent rate limit issues with generating\
    \ new tokens too often.\n\n    {\"email\":\"my.user@skai.io\",\"expires_in\":21600,\"\
    access_token\":\"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzaGxvbWkuY29oZW5Ac2thaS5pbyIsImV4cCI6MTcxNDU2NjgxMSwiaXNzIjoiaHR0cDovL2tlbnNob28uY29tL2xvZ2luLXNlcnZlciIsInVzZXJpZCI6MzU5NDMsImFnZW5jeUlkIjoxNSwibmFtZSI6IlNobG9taSBDb2hlbiIsInJvbGVzIjpbIktlbnNob28gQWRtaW4iLCJTa2FpIERldmVsb3BlciJdLCJhZ2VuY3lfcm9sZXMiOlt7ImFnZW5jeUlkIjoxNSwicm9sZSI6IktlbnNob28gQWRtaW4ifV0sImJpbGxpbmdJZCI6OTIwMzEsImFwaWMiOiI5MjAzMSIsIm9yaSI6ImFwaSIsImFsbG93ZWRfYXBwcyI6W119.R3tHoaecUrMGzijnF5suo9SVsffXWbWxdMv5fdB3Jx8\"\
    }\n\n\n\n\n\n#### Step 3: Making an API call\nWith any API call to all Skai APIs,\
    \ you must send a valid *access token* in the Authorization header when making\
    \ requests. For example:\n\n    curl -H \"Authorization: Bearer <token>\" -X POST\
    \ \\\n    https://services.kenshoo.com/api/v1/campaigns\n\n\n## Rate Limits\n\
    API calls are limited per user, to the following:\n  - 60 requests per minute\n\
    \  - 2,000 requests per hour\n\nWhen you meet the limit, you receive the following\
    \ 429 HTTP error: “API rate limit exceeded”.\nWhen calling any API endpoint the\
    \ response headers will show the limits relevant to this user, and the number\
    \ of remaining calls you can make within the current minute/hour.\n\n\n## Reporting\
    \ Best Practices\n\n- **Filter for non-zero data:** For performance reports, filter\
    \ to rows where a key metric (e.g., impressions > 0) to reduce report size and\
    \ speed up generation.\n- **Scope structure reports:** Apply a filter like \"\
    Last updated > X days ago\" to retrieve only recently changed entities.\n- **Use\
    \ Async for large datasets:** If your report may return more than a few thousand\
    \ rows, use [Async Analysis Reports](#tag/Asynchronous-Reports) and poll for results\
    \ rather than the synchronous endpoint.\n\n\n## Group by and Segmentation\n###\
    \ Understanding Group by and Segmentation\nWhen querying the /api/v1/reports/async/analysis\
    \ and /reports endpoints, the breakdown_type parameter\ndetermines how data is\
    \ structured.\n- FLAT: Returns unsegmented data without any grouping.\n- GROUP:\
    \ Allows data segmentation based on specified columns (e.g., by date).\n- SEGMENT:\
    \ Enables segmentation by date and an additional column, such as CampaignId.\n\
    \n### How Group by works\nWhen using \"breakdown_type\": \"GROUP\", the group_bys\
    \ parameter defines how the data is grouped. For instance:\n\"group_bys\": [ {\
    \ \"name\": \"Day\", \"group\": \"TimeSegment\" } ]\n               This groups\
    \ data only by date, meaning campaign details won’t be included, similar to what\
    \ is displayed in the grid export.\n\n| Conv. | Cost | Day        |\n|-------|------|------------|\n\
    |   2   |  100 | 09/29/2024 |\n|   3   |  200 | 09/28/2024 |\n\n### Using SEGMENT\
    \ for Additional Grouping\nTo segment data by both date and another column (e.g.,\
    \ CampaignId), use \"breakdown_type\": \"SEGMENT\", specifying only the date column\
    \ under group_bys while including the additional column in fields. Example:\n\"\
    breakdown_type\": \"SEGMENT\",\n\"group_bys\": [ { \"name\": \"Day\", \"group\"\
    : \"TimeSegment\" } ],\n\"fields\": [ { \"name\": \"CampaignId\", \"group\": \"\
    ATTRIBUTES\" } ]\n\nThis ensures data is segmented by day while preserving campaign\
    \ details.\n\n| Campaign ID | Conv. | Cost | Day        |\n|-------------|-------|------|------------|\n\
    | 25000       |   1   |  50  | 09/29/2024 |\n| 25001       |   1   |  50  | 09/29/2024\
    \ |\n| 25000       |   2   |  150 | 09/28/2024 |\n| 25001       |   1   |  50\
    \  | 09/28/2024 |\n"
  version: "1.0.0"
  x-logo:
    url: "https://grid.kenshoo.com/resources-frontend/latest/kenshoo_logo/skai-logo-devportal.svg"
    backgroundColor: "#FFFFFF"
    altText: "Skai"
servers:
- url: "https://services.kenshoo.com"
security:
- BearerAuth: []
tags:
- name: "Profile"
  description: "<dl>\n<span>Publishers:</span>\n<span style=\"color: white; padding:\
    \ 8px; background-color: #4CAF50;\" >Search</span>\n<span style=\"color: white;\
    \ padding: 8px; background-color: #2196F3;\" >Social (excl. Meta)</span>\n<span\
    \ style=\"color: white; padding: 8px; background-color: #A29A22;\" >Retail Media</span>\n\
    </dl>\n"
- name: "Campaigns"
  description: "Create, update, and retrieve campaigns.\n\n> **Scope:** This API covers\
    \ common campaign attributes — name, budget, bid, status, dates, and campaign\
    \ type.\n> For the full range of campaign settings (targeting, extensions, dimension\
    \ labels, and publisher-specific fields)\n> use [Bulk Update (One File)](#tag/Bulk-Update),\
    \ which handles millions of rows across all non-Meta publishers.\n\n<dl>\n<span>Publishers:</span>\n\
    <span style=\"color: white; padding: 8px; background-color: #4CAF50;\" >Search</span>\n\
    <span style=\"color: white; padding: 8px; background-color: #2196F3;\" >Social\
    \ (excl. Meta)</span>\n<span style=\"color: white; padding: 8px; background-color:\
    \ #A29A22;\" >Retail Media</span>\n</dl>\n"
- name: "Ad Groups"
  description: "Create, update, and retrieve ad groups.\n\n> **Scope:** This API covers\
    \ common ad group attributes — name, bid, status, and targeting basics.\n> For\
    \ the full range of ad group settings use [Bulk Update (One File)](#tag/Bulk-Update).\n\
    \n<dl>\n<span>Publishers:</span>\n<span style=\"color: white; padding: 8px; background-color:\
    \ #4CAF50;\" >Search</span>\n<span style=\"color: white; padding: 8px; background-color:\
    \ #2196F3;\" >Social (excl. Meta)</span>\n<span style=\"color: white; padding:\
    \ 8px; background-color: #A29A22;\" >Retail Media</span>\n</dl>\n"
- name: "Ads"
  description: "Create, update, and retrieve ads.\n\n> **Scope:** This API covers\
    \ status updates and tag management for ads.\n> For full ad creation and attribute\
    \ management use [Bulk Update (One File)](#tag/Bulk-Update).\n\n<dl>\n<span>Publishers:</span>\n\
    <span style=\"color: white; padding: 8px; background-color: #4CAF50;\" >Search</span>\n\
    <span style=\"color: white; padding: 8px; background-color: #2196F3;\" >Social\
    \ (excl. Meta)</span>\n<span style=\"color: white; padding: 8px; background-color:\
    \ #A29A22;\" >Retail Media</span>\n</dl>\n"
- name: "Product Groups"
  description: "Create, update, and retrieve product groups for Shopping campaigns.\n\
    \n> **Scope:** Covers product group creation and status updates.\n> For bulk product\
    \ group management use [Bulk Update (One File)](#tag/Bulk-Update).\n\n<dl>\n<span>Publishers:</span>\n\
    <span style=\"color: white; padding: 8px; background-color: #2196F3;\" >Search\
    \ Shopping</span>\n<span style=\"color: white; padding: 8px; background-color:\
    \ #f44336;\" >Pinterest Shopping</span>\n</dl>\n"
- name: "Portfolios"
  description: "Retrieve and update portfolio budgets and settings.\n\n<dl>\n<span>Publishers:</span>\n\
    <span style=\"color: white; padding: 8px; background-color: #4CAF50;\" >Search</span>\n\
    <span style=\"color: white; padding: 8px; background-color: #2196F3;\" >Social\
    \ (excl. Meta)</span>\n<span style=\"color: white; padding: 8px; background-color:\
    \ #A29A22;\" >Retail Media</span>\n</dl>\n"
- name: "Meta Campaigns"
  description: "Manage dimension tags on Meta campaigns.\n\n> **Scope:** This section\
    \ covers applying and removing Skai dimension labels on Meta campaigns.\n> For\
    \ Meta campaign creation and full management, contact your Skai account team.\n\
    \n<dl>\n<span>Publishers:</span>\n<span style=\"color: white; padding: 8px; background-color:\
    \ #326bc7;\" >Meta</span>\n</dl>\n"
- name: "Meta Ad Groups"
  description: "Manage dimension tags on Meta ad groups.\n\n> **Scope:** This section\
    \ covers applying and removing Skai dimension labels on Meta ad groups.\n\n<dl>\n\
    <span>Publishers:</span>\n<span style=\"color: white; padding: 8px; background-color:\
    \ #326bc7;\" >Meta</span>\n</dl>\n"
- name: "Meta Ads"
  description: "Manage dimension tags on Meta ads.\n\n> **Scope:** This section covers\
    \ applying and removing Skai dimension labels on Meta ads.\n\n<dl>\n<span>Publishers:</span>\n\
    <span style=\"color: white; padding: 8px; background-color: #326bc7;\" >Meta</span>\n\
    </dl>\n"
- name: "Reports"
  description: "<dl>\n<span>Publishers:</span>\n<span style=\"color: white; padding:\
    \ 8px; background-color: #4CAF50;\" >Search</span>\n<span style=\"color: white;\
    \ padding: 8px; background-color: #2196F3;\" >Social (incl. Meta)</span>\n<span\
    \ style=\"color: white; padding: 8px; background-color: #A29A22;\" >Retail Media</span>\n\
    </dl>\n"
- name: "Async Reports"
  description: "<dl>\n<span>Publishers:</span>\n<span style=\"color: white; padding:\
    \ 8px; background-color: #4CAF50;\" >Search</span>\n<span style=\"color: white;\
    \ padding: 8px; background-color: #2196F3;\" >Social (incl. Meta)</span>\n<span\
    \ style=\"color: white; padding: 8px; background-color: #A29A22;\" >Retail Media</span>\n\
    </dl>\n"
- name: "Jobs"
  description: "Operations that can take more than a few seconds are defined as **jobs**.\n\
    Initiating such operations will return a _job_id_, which can then be used to query\
    \ the status of the job, and once completed to query the job results.\n"
- name: "Bulk Update"
  description: "<dl>\n<span>Publishers:</span>\n<span style=\"color: white; padding:\
    \ 8px; background-color: #4CAF50;\" >Search</span>\n<span style=\"color: white;\
    \ padding: 8px; background-color: #2196F3;\" >Social (excl. Meta)</span>\n<span\
    \ style=\"color: white; padding: 8px; background-color: #A29A22;\" >Retail Media</span>\n\
    </dl>\n"
- name: "MCP"
  description: "The Skai **Model Context Protocol (MCP) server** lets AI coding assistants\
    \ query your Skai\ndata and take actions directly inside your development environment\
    \ — no custom API code required.\n\n**Supported clients:** Claude Code, Claude\
    \ Desktop, Claude Web, Cursor, VS Code, Windsurf, ChatGPT\n\n**Setup guide:**\
    \ https://skai-mcp-guide.vercel.app/\n\n**Authentication:** Generate a Personal\
    \ Access Token (PAT) at https://login.kenshoo.com/api/dev/refresh-token\n(valid\
    \ 90 days, separate from the standard API Bearer token).\n\n**Available MCP tools:**\n\
    \n| Tool | Description |\n|------|-------------|\n| `fetch_report` | Retrieve\
    \ reporting data for campaigns, ad groups, keywords, ads, or products |\n| `relevant_columns`\
    \ | Identify which columns are applicable for a given query |\n| `get_today` |\
    \ Get current-day reporting metrics |\n| `get_change_log` | Retrieve the change\
    \ log for campaigns and other entities |\n| `get_competitive_context` | Retrieve\
    \ competitive brand data and context |\n\n**Quick setup for Claude Code** — add\
    \ to `.claude/settings.json`:\n```json\n{\n  \"mcpServers\": {\n    \"skai\":\
    \ {\n      \"type\": \"http\",\n      \"url\": \"https://mcp.kenshoo.com/reports-mcp\"\
    ,\n      \"headers\": {\n        \"Authorization\": \"Bearer <YOUR_PAT_TOKEN>\"\
    ,\n        \"ks-name\": \"<YOUR_KS_NAME>\"\n      }\n    }\n  }\n}\n```\n\nFor\
    \ other platforms (Cursor, ChatGPT, Claude Desktop) see the full setup guide at\
    \ https://skai-mcp-guide.vercel.app/\n"
paths:
  /api/v1/add-ons/{addon_id}:
    get:
      summary: "get addon usage by id and billing account id"
      operationId: "getAddonUsage"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/accounts/{billingAccountId}/add-ons-request:
    post:
      summary: "create add ons request"
      operationId: "requestAddon"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/accounts/addon-request:
    post:
      summary: "create add ons request"
      operationId: "requestAddonNew"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/accounts/{billingAccountId}/addons:
    get:
      summary: "get account addons data"
      operationId: "getAddonsData"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/add-ons:
    get:
      summary: "get addons usage by billing account id"
      operationId: "getAddonsUsage"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/accounts/spend:
    get:
      summary: "get account spend data"
      operationId: "getSpendDataNew"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/add-ons/{billingAccountId}/usage:
    put:
      summary: "update add-on usage data"
      operationId: "updateAddonUsage"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/accounts/topmost-parent:
    get:
      summary: "get topmost parent by billing account id"
      operationId: "getTopmostParent"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/accounts/addons:
    get:
      summary: "get account addons data"
      operationId: "getAddonsDataNew"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/accounts/{billingAccountId}/data:
    get:
      summary: "get account plan overview data"
      operationId: "getAccountData"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/accounts/{billingAccountId}/spend:
    get:
      summary: "get account spend data"
      operationId: "getSpendData"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/relevant-columns:
    post:
      summary: "Get relevant columns"
      operationId: "getRelevantColumns"
      responses:
        200:
          description: "200 response"
        400:
          description: "400 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/spotlight:
    post:
      summary: "request spotlight and segments data"
      operationId: "createSpotlight"
      responses:
        200:
          description: "200 response"
        400:
          description: "400 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/spotlights/ai/conversation/message:
    post:
      summary: "ask a question"
      operationId: "askSpotlightAiQuestion"
      responses:
        200:
          description: "200 response"
        400:
          description: "400 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/spotlights/available_metrics:
    get:
      summary: "request spotlight and segments data"
      operationId: "getSpotlightMetrics"
      responses:
        200:
          description: "200 response"
        400:
          description: "400 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/spotlight/read-status:
    post:
      summary: "update spotlight read status"
      operationId: "markSpotlightRead"
      responses:
        200:
          description: "200 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/spotlights/ai/conversation/message/{messageId}:
    get:
      summary: "ask a question"
      operationId: "getSpotlightAiAnswer"
      responses:
        200:
          description: "200 response"
        400:
          description: "400 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/spotlights/ai/conversation:
    post:
      summary: "request conversation"
      operationId: "createSpotlightAiConversation"
      responses:
        200:
          description: "200 response"
        400:
          description: "400 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/spotlight/export:
    post:
      summary: "exports spotlights of specific KS, view and profiles."
      operationId: "exportSpotlight"
      responses:
        200:
          description: "200 response"
        401:
          description: "User unauthorized"
        500:
          description: "unexpected error"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/spotlight/pivot-drill-down:
    post:
      summary: "request spotlight pivot drill down"
      operationId: "spotlightPivotDrillDown"
      responses:
        200:
          description: "200 response"
        400:
          description: "400 response"
        500:
          description: "500 response"
    options:
      description: "For cross-origin requests"
      responses:
        default:
          description: "The operation was completed successfully"
  /api/v1/incrementality/agencies/{agency_id}/data_sources/{data_source_id}:
    put:
      summary: "update data source"
      operationId: "updateDataSource"
      parameters:
      - name: "agency_id"
        in: "path"
        required: true
        style: "simple"
        explode: false
        schema:
          type: "integer"
          format: "int32"
      - name: "data_source_id"
        in: "path"
        required: true
        style: "simple"
        explode: false
        schema:
          type: "integer"
          format: "int32"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
    options:
      summary: "update data source options"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
  /api/v1/incrementality/agencies/{agency_id}/data_sources/info:
    post:
      summary: "get data source info by name"
      operationId: "getDataSourceInfo"
      parameters:
      - name: "agency_id"
        in: "path"
        required: true
        style: "simple"
        explode: false
        schema:
          type: "integer"
          format: "int32"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
    options:
      summary: "get data source info by name options"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
  /api/v1/incrementality/agencies/{agency_id}/data_load_tasks/{data_load_task_id}:
    get:
      summary: "get data load task new"
      operationId: "getDataLoadTaskForAgency"
      parameters:
      - name: "agency_id"
        in: "path"
        required: true
        style: "simple"
        explode: false
        schema:
          type: "integer"
          format: "int32"
      - name: "data_load_task_id"
        in: "path"
        required: true
        style: "simple"
        explode: false
        schema:
          type: "integer"
          format: "int32"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
    options:
      summary: "incrementality data loader options"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
  /api/v1/incrementality/files/upload:
    post:
      summary: "Upload source file to S3"
      operationId: "uploadSourceFile"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
    options:
      summary: "incrementality data loader options"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
  /api/v1/incrementality/agencies/{agency_id}/data_load_tasks:
    post:
      summary: "create new data load task - new"
      operationId: "createDataLoadTaskForAgency"
      parameters:
      - name: "agency_id"
        in: "path"
        required: true
        style: "simple"
        explode: false
        schema:
          type: "integer"
          format: "int32"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
    options:
      summary: "incrementality data loader options"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
  /api/v1/incrementality/data_load_tasks:
    post:
      summary: "create new data load task"
      operationId: "createDataLoadTask"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
    options:
      summary: "incrementality data loader options"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
  /api/v1/incrementality/agencies/{agency_id}/data_sources/{data_source_id}/status:
    get:
      summary: "get data status"
      operationId: "getDataSourceStatus"
      parameters:
      - name: "agency_id"
        in: "path"
        required: true
        style: "simple"
        explode: false
        schema:
          type: "integer"
          format: "int32"
      - name: "data_source_id"
        in: "path"
        required: true
        style: "simple"
        explode: false
        schema:
          type: "integer"
          format: "int32"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
    options:
      summary: "get data status options"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
  /api/v1/incrementality/agencies/{agency_id}/data_sources:
    post:
      summary: "create new data source"
      operationId: "createDataSource"
      parameters:
      - name: "agency_id"
        in: "path"
        required: true
        style: "simple"
        explode: false
        schema:
          type: "integer"
          format: "int32"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
    options:
      summary: "create new data source options"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
  /api/v1/incrementality/data_load_tasks/{task_id}:
    get:
      summary: "get data load task"
      operationId: "getDataLoadTask"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
    options:
      summary: "incrementality data loader options"
      responses:
        200:
          description: "200 response"
        300:
          description: "300 response"
  /api/v2/agencies/{agency_id}/monitoring/results-explanation-file:
    get:
      summary: "Get test result explanation file"
      parameters:
      - name: "agency_id"
        in: "path"
        required: true
        style: "simple"
        explode: false
        schema:
          type: "integer"
          for

# --- truncated at 32 KB (562 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/skai-kenshoo/refs/heads/main/openapi/skai-kenshoo-api-openapi.yml