diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 53ef42c..c9d69ee 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -30,7 +30,7 @@ jobs: - name: Validate JSON matches YAML run: | - npm install -g js-yaml + npm install --no-save js-yaml node -e " const fs = require('fs'); const yaml = require('js-yaml'); diff --git a/openapi/data-api.json b/openapi/data-api.json index f30b23f..6cac094 100644 --- a/openapi/data-api.json +++ b/openapi/data-api.json @@ -5094,7 +5094,7 @@ ], "responses": { "200": { - "description": "Successful response", + "description": "Successful response.\n\nChanges since 2026-09-29 (new AI Search data source):\n\n- `summary.average_position` is always `null`.\n- `time_series.organic_traffic`, `time_series.overall_traffic` and\n `time_series.average_position` are empty arrays.\n- `summary.brand_presence` counts the prompts whose answer mentions the\n brand as a recognized entity, instead of a text match on the brand\n name.\n- `summary.*.previous` is the value of the previous monthly snapshot\n (`null` when unknown), and `change_absolute` / `change_percent` are\n computed from it and signed. Before, `previous` was always `null`\n and the change was reported as the current value and 100%.", "content": { "application/json": {} } @@ -5168,7 +5168,7 @@ ], "responses": { "200": { - "description": "Successful response", + "description": "Successful response.\n\nChanges since 2026-09-29 (new AI Search data source):\n\n- `summary.average_position` is always `null`.\n- `time_series.organic_traffic`, `time_series.overall_traffic` and\n `time_series.average_position` are empty arrays.\n- `summary.brand_presence` counts the prompts whose answer mentions the\n brand as a recognized entity, instead of a text match on the brand\n name.\n- `summary.*.previous` is the value of the previous monthly snapshot\n (`null` when unknown), and `change_absolute` / `change_percent` are\n computed from it and signed. Before, `previous` was always `null`\n and the change was reported as the current value and 100%.", "content": { "application/json": {} } @@ -5244,7 +5244,7 @@ ], "responses": { "200": { - "description": "Successful response", + "description": "Successful response.\n\nSince 2026-09-29 (new AI Search data source) `brand_presence` counts\nthe prompts whose answer mentions the brand as a recognized entity,\ninstead of a text match on the brand name.", "content": { "application/json": {} } @@ -5318,7 +5318,7 @@ "AI search" ], "summary": "prompts by target", - "description": "Fetches a list of prompts where a specified domain, subdomain, or URL appears in the results of a chosen LLM.", + "description": "Fetches a list of prompts where a specified domain, subdomain, or URL appears in the results of a chosen LLM.\n\nThe `filter[volume]`, `filter[keyword_count]` and `filter[characters_count]` filters were removed on 2026-10-14. A page holds at most 1000 prompts (`limit`).", "parameters": [ { "name": "apikey", @@ -5400,8 +5400,10 @@ "name": "limit", "in": "query", "schema": { - "type": "integer" + "type": "integer", + "maximum": 1000 }, + "description": "Number of prompts per page, at most 1000. A larger value is rejected with 400.", "example": 100 }, { @@ -5423,6 +5425,8 @@ { "name": "filter[volume][from]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5431,6 +5435,8 @@ { "name": "filter[volume][to]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5439,6 +5445,8 @@ { "name": "filter[keyword_count][from]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5447,6 +5455,8 @@ { "name": "filter[keyword_count][to]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5455,6 +5465,8 @@ { "name": "filter[characters_count][from]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5463,6 +5475,8 @@ { "name": "filter[characters_count][to]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5471,7 +5485,13 @@ ], "responses": { "200": { - "description": "Successful response", + "description": "Successful response.\n\nChanges since 2026-09-29 (new AI Search data source):\n\n- `prompts[].volume` is `null` for `engine=ai-overview` and `0` for\n the LLM engines.\n- `date` is the current month.", + "content": { + "application/json": {} + } + }, + "400": { + "description": "Invalid request, e.g. `limit` above 1000 or a filter that is no longer supported (`unsupported filter`).", "content": { "application/json": {} } @@ -5486,7 +5506,7 @@ "AI search" ], "summary": "prompts by brand", - "description": "Retrieves a list of prompts where a specified brand name is mentioned in the results of a chosen LLM.", + "description": "Retrieves a list of prompts where a specified brand name is mentioned in the results of a chosen LLM.\n\nThe `filter[volume]`, `filter[keyword_count]` and `filter[characters_count]` filters were removed on 2026-10-14. A page holds at most 1000 prompts (`limit`).", "parameters": [ { "name": "apikey", @@ -5559,8 +5579,10 @@ "name": "limit", "in": "query", "schema": { - "type": "integer" + "type": "integer", + "maximum": 1000 }, + "description": "Number of prompts per page, at most 1000. A larger value is rejected with 400.", "example": 10 }, { @@ -5582,6 +5604,8 @@ { "name": "filter[volume][from]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5590,6 +5614,8 @@ { "name": "filter[volume][to]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5598,6 +5624,8 @@ { "name": "filter[keyword_count][from]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5606,6 +5634,8 @@ { "name": "filter[keyword_count][to]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5614,6 +5644,8 @@ { "name": "filter[characters_count][from]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5622,6 +5654,8 @@ { "name": "filter[characters_count][to]", "in": "query", + "deprecated": true, + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5630,7 +5664,13 @@ ], "responses": { "200": { - "description": "Successful response", + "description": "Successful response.\n\nChanges since 2026-09-29 (new AI Search data source):\n\n- `prompts[].volume` is `null` for `engine=ai-overview` and `0` for\n the LLM engines.\n- `date` is the current month.", + "content": { + "application/json": {} + } + }, + "400": { + "description": "Invalid request, e.g. `limit` above 1000 or a filter that is no longer supported (`unsupported filter`).", "content": { "application/json": {} } diff --git a/openapi/data-api.yaml b/openapi/data-api.yaml index ee2e74d..858f039 100644 --- a/openapi/data-api.yaml +++ b/openapi/data-api.yaml @@ -3809,7 +3809,21 @@ paths: example: base_domain responses: '200': - description: Successful response + description: |- + Successful response. + + Changes since 2026-09-29 (new AI Search data source): + + - `summary.average_position` is always `null`. + - `time_series.organic_traffic`, `time_series.overall_traffic` and + `time_series.average_position` are empty arrays. + - `summary.brand_presence` counts the prompts whose answer mentions the + brand as a recognized entity, instead of a text match on the brand + name. + - `summary.*.previous` is the value of the previous monthly snapshot + (`null` when unknown), and `change_absolute` / `change_percent` are + computed from it and signed. Before, `previous` was always `null` + and the change was reported as the current value and 100%. content: application/json: {} /v1/ai-search/overview/by-engine/time-series: @@ -3859,7 +3873,21 @@ paths: example: base_domain responses: '200': - description: Successful response + description: |- + Successful response. + + Changes since 2026-09-29 (new AI Search data source): + + - `summary.average_position` is always `null`. + - `time_series.organic_traffic`, `time_series.overall_traffic` and + `time_series.average_position` are empty arrays. + - `summary.brand_presence` counts the prompts whose answer mentions the + brand as a recognized entity, instead of a text match on the brand + name. + - `summary.*.previous` is the value of the previous monthly snapshot + (`null` when unknown), and `change_absolute` / `change_percent` are + computed from it and signed. Before, `previous` was always `null` + and the change was reported as the current value and 100%. content: application/json: {} /v1/ai-search/overview/leaderboard: @@ -3909,7 +3937,12 @@ paths: example: base_domain responses: '200': - description: Successful response + description: |- + Successful response. + + Since 2026-09-29 (new AI Search data source) `brand_presence` counts + the prompts whose answer mentions the brand as a recognized entity, + instead of a text match on the brand name. content: application/json: {} /v1/ai-search/discover-brand: @@ -3965,6 +3998,11 @@ paths: description: >- Fetches a list of prompts where a specified domain, subdomain, or URL appears in the results of a chosen LLM. + + + The `filter[volume]`, `filter[keyword_count]` and + `filter[characters_count]` filters were removed + on 2026-10-14. A page holds at most 1000 prompts (`limit`). parameters: - name: apikey in: query @@ -4023,6 +4061,10 @@ paths: in: query schema: type: integer + maximum: 1000 + description: >- + Number of prompts per page, at most 1000. A larger value is rejected + with 400. example: 100 - name: filter[multi_keyword_included] in: query @@ -4053,37 +4095,74 @@ paths: ] - name: filter[volume][from] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 100 - name: filter[volume][to] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 100000 - name: filter[keyword_count][from] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 5 - name: filter[keyword_count][to] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 8 - name: filter[characters_count][from] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 15 - name: filter[characters_count][to] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 50 responses: '200': - description: Successful response + description: |- + Successful response. + + Changes since 2026-09-29 (new AI Search data source): + + - `prompts[].volume` is `null` for `engine=ai-overview` and `0` for + the LLM engines. + - `date` is the current month. + content: + application/json: {} + '400': + description: >- + Invalid request, e.g. `limit` above 1000 or a filter that is no + longer supported (`unsupported filter`). content: application/json: {} /v1/ai-search/prompts-by-brand: @@ -4095,6 +4174,11 @@ paths: description: >- Retrieves a list of prompts where a specified brand name is mentioned in the results of a chosen LLM. + + + The `filter[volume]`, `filter[keyword_count]` and + `filter[characters_count]` filters were removed + on 2026-10-14. A page holds at most 1000 prompts (`limit`). parameters: - name: apikey in: query @@ -4144,6 +4228,10 @@ paths: in: query schema: type: integer + maximum: 1000 + description: >- + Number of prompts per page, at most 1000. A larger value is rejected + with 400. example: 10 - name: filter[multi_keyword_included] in: query @@ -4174,37 +4262,74 @@ paths: ] - name: filter[volume][from] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 100 - name: filter[volume][to] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 100000 - name: filter[keyword_count][from] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 5 - name: filter[keyword_count][to] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 8 - name: filter[characters_count][from] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 15 - name: filter[characters_count][to] in: query + deprecated: true + description: >- + Removed on 2026-10-14; requests that use it get 400 unsupported + filter. schema: type: integer example: 50 responses: '200': - description: Successful response + description: |- + Successful response. + + Changes since 2026-09-29 (new AI Search data source): + + - `prompts[].volume` is `null` for `engine=ai-overview` and `0` for + the LLM engines. + - `date` is the current month. + content: + application/json: {} + '400': + description: >- + Invalid request, e.g. `limit` above 1000 or a filter that is no + longer supported (`unsupported filter`). content: application/json: {} /v1/serp/classic/tasks: