{"swagger": "2.0", "info": {"title": "Ranketta - Public API", "description": "Ranketta exposes a versioned REST API at `api.ranketta.com/v1/`. All\nendpoints require a Bearer token issued from **Settings → API keys** in\nthe dashboard.\n\n```http\nAuthorization: Bearer rkt_live_...\n```\n\nEach key is scoped to a single company and ships with a per-key request\nbudget, a default webhook callback URL, and a signing secret.\n\n## Webhook IP allowlisting\n\nWebhook deliveries are sent from a fixed egress IP:\n\n```\n166.0.78.90\n```\n\nYou may allowlist this address in your firewall or WAF as optional\nhardening. **Always verify `X-Ranketta-Signature`** — HMAC verification\nis the required security control; IP allowlisting alone is not\nsufficient.\n\n## Rate limits\n\nEach API key has a `rate_limit_per_minute` setting (default 60).\nExceeding it returns `429 Too Many Requests`.\n", "contact": {"email": "info@ranketta.com"}, "license": {"name": "Proprietary"}, "version": "v1"}, "host": "api.ranketta.com", "schemes": ["https"], "basePath": "/", "consumes": ["application/json"], "produces": ["application/json"], "securityDefinitions": {"Bearer": {"type": "apiKey", "name": "Authorization", "in": "header", "description": "Bearer token from the Ranketta dashboard. Example: `Bearer rkt_live_abc123…`"}}, "security": [{"Bearer": []}], "paths": {"/citations/overall/domains/": {"get": {"operationId": "list_citation_domains", "summary": "Domains cited by AI models", "description": "Returns the domains cited in AI responses across all prompts for the company, with each domain's citation share (percentage of completions in which it appeared). Supports filtering by prompt, topic, tag and date range.", "parameters": [{"name": "start_date", "in": "query", "description": "ISO 8601 start date. Defaults to 30 days before today if omitted.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date. Defaults to today if omitted.", "type": "string"}, {"name": "prompt_ids", "in": "query", "description": "Comma-separated prompt IDs to filter by.", "type": "string"}, {"name": "topic_ids", "in": "query", "description": "Comma-separated topic IDs.", "type": "string"}, {"name": "search", "in": "query", "description": "Search string to filter domain names.", "type": "string"}, {"name": "country_ids", "in": "query", "description": "Comma-separated country IDs.", "type": "string"}, {"name": "provider_ids", "in": "query", "description": "Comma-separated provider IDs.", "type": "string"}, {"name": "tag_ids", "in": "query", "description": "Comma-separated prompt tag IDs.", "type": "string"}, {"name": "domain_types", "in": "query", "description": "Filter by domain type (repeat param for multiple values).", "type": "string"}, {"name": "page_types", "in": "query", "description": "Filter by page type (repeat param for multiple values).", "type": "string"}, {"name": "mentioned", "in": "query", "description": "Filter by customer mention status: true, false, or all.", "type": "string"}, {"name": "http_status_codes", "in": "query", "description": "Filter by HTTP status codes returned when fetching cited pages (repeat param or comma-separated).", "type": "string"}, {"name": "competitor_ids", "in": "query", "description": "Comma-separated competitor IDs to filter by (only citations mentioning these competitors).", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/SourceAggregate"}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Citations"], "security": [{"Bearer": []}]}, "parameters": []}, "/citations/overall/domains/type-breakdown/": {"get": {"operationId": "citation_domain_types_breakdown", "summary": "Citation share by domain type", "description": "Returns citation share percentages grouped by domain_type (corporate, ugc, editorial, etc.).", "parameters": [{"name": "start_date", "in": "query", "description": "ISO 8601 start date. Defaults to 30 days before today if omitted.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date. Defaults to today if omitted.", "type": "string"}, {"name": "prompt_ids", "in": "query", "description": "Comma-separated prompt IDs to filter by.", "type": "string"}, {"name": "search", "in": "query", "description": "Search string to filter domains/URLs.", "type": "string"}, {"name": "country_ids", "in": "query", "description": "Comma-separated country IDs.", "type": "string"}, {"name": "provider_ids", "in": "query", "description": "Comma-separated provider IDs.", "type": "string"}, {"name": "tag_ids", "in": "query", "description": "Comma-separated prompt tag IDs.", "type": "string"}, {"name": "domain_types", "in": "query", "description": "Filter by domain type (repeat param for multiple values).", "type": "string"}, {"name": "page_types", "in": "query", "description": "Filter by page type (repeat param for multiple values).", "type": "string"}, {"name": "mentioned", "in": "query", "description": "Filter by customer mention status: true, false, or all.", "type": "string"}, {"name": "http_status_codes", "in": "query", "description": "Filter by HTTP status codes returned when fetching cited pages (repeat param or comma-separated).", "type": "string"}, {"name": "competitor_ids", "in": "query", "description": "Comma-separated competitor IDs to filter by (only citations mentioning these competitors).", "type": "string"}], "responses": {"200": {"description": "Type breakdown payload."}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Citations"], "security": [{"Bearer": []}]}, "parameters": []}, "/citations/overall/stats/": {"get": {"operationId": "citation_overall_stats", "summary": "Citation overview stats", "description": "Returns citation KPIs counted as distinct pages (normalized URLs), not citation rows: unique pages, covered pages (brand mentioned at least once), mention rate (covered ÷ unique pages), and unique domains. Each metric includes a variation versus the previous period of equal length.", "parameters": [{"name": "start_date", "in": "query", "description": "ISO 8601 start date. Defaults to 30 days before today if omitted.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date. Defaults to today if omitted.", "type": "string"}, {"name": "prompt_ids", "in": "query", "description": "Comma-separated prompt IDs to filter by.", "type": "string"}, {"name": "search", "in": "query", "description": "Search string to filter domains/URLs.", "type": "string"}, {"name": "country_ids", "in": "query", "description": "Comma-separated country IDs.", "type": "string"}, {"name": "provider_ids", "in": "query", "description": "Comma-separated provider IDs.", "type": "string"}, {"name": "tag_ids", "in": "query", "description": "Comma-separated prompt tag IDs.", "type": "string"}, {"name": "domain_types", "in": "query", "description": "Filter by domain type (repeat param for multiple values).", "type": "string"}, {"name": "page_types", "in": "query", "description": "Filter by page type (repeat param for multiple values).", "type": "string"}, {"name": "mentioned", "in": "query", "description": "Filter by customer mention status: true, false, or all.", "type": "string"}, {"name": "http_status_codes", "in": "query", "description": "Filter by HTTP status codes returned when fetching cited pages (repeat param or comma-separated).", "type": "string"}, {"name": "competitor_ids", "in": "query", "description": "Comma-separated competitor IDs to filter by (only citations mentioning these competitors).", "type": "string"}], "responses": {"200": {"description": "Citation overview stats payload."}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Citations"], "security": [{"Bearer": []}]}, "parameters": []}, "/citations/overall/urls/": {"get": {"operationId": "list_citation_urls", "summary": "URLs cited by AI models", "description": "Returns the specific URLs cited in AI responses across all prompts, with tracking parameters stripped and each URL's citation share. Supports the same filters as the domains endpoint.", "parameters": [{"name": "start_date", "in": "query", "description": "ISO 8601 start date. Defaults to 30 days before today if omitted.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date. Defaults to today if omitted.", "type": "string"}, {"name": "prompt_ids", "in": "query", "description": "Comma-separated prompt IDs to filter by.", "type": "string"}, {"name": "topic_ids", "in": "query", "description": "Comma-separated topic IDs.", "type": "string"}, {"name": "search", "in": "query", "description": "Search string to filter URLs.", "type": "string"}, {"name": "domain_names", "in": "query", "description": "Filter URLs to these citation domains (repeat param for multiple values).", "type": "string"}, {"name": "country_ids", "in": "query", "description": "Comma-separated country IDs.", "type": "string"}, {"name": "provider_ids", "in": "query", "description": "Comma-separated provider IDs.", "type": "string"}, {"name": "tag_ids", "in": "query", "description": "Comma-separated prompt tag IDs.", "type": "string"}, {"name": "domain_types", "in": "query", "description": "Filter by domain type (repeat param for multiple values).", "type": "string"}, {"name": "page_types", "in": "query", "description": "Filter by page type (repeat param for multiple values).", "type": "string"}, {"name": "mentioned", "in": "query", "description": "Filter by customer mention status: true, false, or all.", "type": "string"}, {"name": "http_status_codes", "in": "query", "description": "Filter by HTTP status codes returned when fetching cited pages (repeat param or comma-separated).", "type": "string"}, {"name": "competitor_ids", "in": "query", "description": "Comma-separated competitor IDs to filter by (only citations mentioning these competitors).", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/SourceAggregate"}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Citations"], "security": [{"Bearer": []}]}, "parameters": []}, "/citations/overall/urls/type-breakdown/": {"get": {"operationId": "citation_page_types_breakdown", "summary": "Citation share by page type", "description": "Returns citation share percentages grouped by page_type (blog_post, product_page, etc.).", "parameters": [{"name": "start_date", "in": "query", "description": "ISO 8601 start date. Defaults to 30 days before today if omitted.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date. Defaults to today if omitted.", "type": "string"}, {"name": "prompt_ids", "in": "query", "description": "Comma-separated prompt IDs to filter by.", "type": "string"}, {"name": "search", "in": "query", "description": "Search string to filter domains/URLs.", "type": "string"}, {"name": "country_ids", "in": "query", "description": "Comma-separated country IDs.", "type": "string"}, {"name": "provider_ids", "in": "query", "description": "Comma-separated provider IDs.", "type": "string"}, {"name": "tag_ids", "in": "query", "description": "Comma-separated prompt tag IDs.", "type": "string"}, {"name": "domain_types", "in": "query", "description": "Filter by domain type (repeat param for multiple values).", "type": "string"}, {"name": "page_types", "in": "query", "description": "Filter by page type (repeat param for multiple values).", "type": "string"}, {"name": "mentioned", "in": "query", "description": "Filter by customer mention status: true, false, or all.", "type": "string"}, {"name": "http_status_codes", "in": "query", "description": "Filter by HTTP status codes returned when fetching cited pages (repeat param or comma-separated).", "type": "string"}, {"name": "competitor_ids", "in": "query", "description": "Comma-separated competitor IDs to filter by (only citations mentioning these competitors).", "type": "string"}], "responses": {"200": {"description": "Type breakdown payload."}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Citations"], "security": [{"Bearer": []}]}, "parameters": []}, "/content/": {"get": {"operationId": "list_content", "summary": "List content pieces", "description": "Returns all content pieces (articles, landing pages, etc.) created for the company. Supports filtering by status, content type and free-text search.", "parameters": [{"name": "status", "in": "query", "description": "Filter by content status (e.g. draft, published).", "type": "string"}, {"name": "content_type_id", "in": "query", "description": "Filter by content type ID.", "type": "integer"}, {"name": "search", "in": "query", "description": "Search by title or body.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/ContentList"}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Content"], "security": [{"Bearer": []}]}, "post": {"operationId": "create_content", "summary": "Create a new content piece", "description": "Creates a new content piece (article, landing page, etc.) for the company. Requires a title and content type. Optionally links the piece to one or more tracked prompts to seed it with relevant citation and keyword data.", "parameters": [], "responses": {"201": {"description": "", "schema": {"$ref": "#/definitions/Content"}}, "400": {"description": "Validation error."}, "401": {"description": "Missing or invalid API key."}, "402": {"description": "Content quota exceeded."}}, "tags": ["Content"], "security": [{"Bearer": []}]}, "parameters": []}, "/content/{id}/optimise-default/": {"post": {"operationId": "optimise_content", "summary": "Optimise content with default settings", "description": "Triggers an AI-powered optimisation run for the specified content piece using the company's default locale and content type settings.", "parameters": [], "responses": {"202": {"description": "Optimisation started.", "schema": {"type": "object", "properties": {"message": {"type": "string"}, "status": {"type": "string"}, "generation_id": {"type": "string"}}}}, "400": {"description": "Validation error."}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Content not found."}}, "tags": ["Content"], "security": [{"Bearer": []}]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/content/{id}/optimise/": {"post": {"operationId": "optimise_content_seo_geo", "summary": "Optimise content for a specific SEO locale", "description": "Triggers an AI-powered optimisation run for the specified content piece, tailored to a given country and language pair. The response is streamed as the AI generates improvements to the body.", "parameters": [], "responses": {"202": {"description": "Optimisation started.", "schema": {"type": "object", "properties": {"message": {"type": "string"}, "status": {"type": "string"}, "generation_id": {"type": "string"}}}}, "400": {"description": "Validation error."}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Content not found."}}, "tags": ["Content"], "security": [{"Bearer": []}]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/countries/": {"get": {"operationId": "list_countries", "summary": "Available countries", "description": "Returns countries available to your workspace. Use the returned IDs as `country_ids` filter values across prompts, visibility, and chart endpoints.", "parameters": [], "responses": {"200": {"description": "List of countries.", "schema": {"type": "object", "properties": {"countries": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "integer"}, "code": {"description": "ISO 3166-1 alpha-2 country code.", "type": "string"}, "name": {"type": "string"}, "flag_emoji": {"type": "string"}}}}, "default_country": {"description": "Company default country, if set.", "type": "object", "x-nullable": true}}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Reference"], "security": [{"Bearer": []}]}, "parameters": []}, "/countries/languages/": {"get": {"operationId": "list_languages", "summary": "All languages", "description": "Returns all active languages supported by Ranketta. Use the returned IDs as the `language` parameter when creating or optimising content.", "parameters": [], "responses": {"200": {"description": "List of languages.", "schema": {"type": "object", "properties": {"languages": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "integer"}, "code": {"description": "BCP 47 language tag.", "type": "string"}, "name": {"type": "string"}, "native_name": {"type": "string"}}}}}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Reference"], "security": [{"Bearer": []}]}, "parameters": []}, "/enrichments/": {"get": {"operationId": "list_enrichments", "summary": "List recent enrichment requests", "description": "Returns the most recent enrichment requests submitted by this API key, newest first. Useful for back-office dashboards that want to expose enrichment history to operators.", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/EnrichmentRequestStatus"}}}, "401": {"description": "Missing or invalid API key."}, "429": {"description": "Per-key rate limit exceeded. Wait `Retry-After` seconds before issuing the next request."}}, "tags": ["Enrichment"], "security": [{"Bearer": []}]}, "post": {"operationId": "create_enrichments", "summary": "Submit products for enrichment", "description": "Queues one stateless enrichment run per element of `products[]`. Each item produces its own webhook delivery. Per-item validation failures (missing required fields) are reported in `rejected[]`; the rest still get queued. If the subscription quota would be exceeded mid-batch, items beyond the limit are returned in `rejected[]` with `quota_exhausted` instead of failing the whole call.", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/EnrichmentBatchRequest"}}], "responses": {"202": {"description": "At least one item was accepted. `accepted[]` lists queued runs (each with its own `request_id`); `rejected[]` lists items that failed pre-flight.", "examples": {"application/json": {"accepted": [{"index": 0, "product_id": "SKU-1", "request_id": "8b7e2d4f3c4f4e58b6c2a1d6f0c9e1a2", "status": "processing"}], "rejected": [{"index": 1, "product_id": "SKU-2", "error": {"code": "missing_required_field", "message": "Required canonical fields missing: title", "fields": ["title"]}}]}}}, "400": {"description": "Request body failed validation. `fields` enumerates the offending paths.", "examples": {"application/json": {"error": {"code": "validation_error", "message": "Request body failed validation.", "fields": {"products": ["This field is required."]}, "request_id": "8b7e2d4f3c4f4e58b6c2a1d6f0c9e1a2"}}}}, "401": {"description": "Missing or invalid API key."}, "402": {"description": "Subscription quota exhausted before any item could be accepted. Upgrade the plan or wait for the usage window to roll over.", "examples": {"application/json": {"accepted": [], "rejected": [{"index": 0, "product_id": "SKU-1", "error": {"code": "quota_exhausted", "message": "Subscription quota exhausted (1000/1000)."}}]}}}, "429": {"description": "Per-key rate limit exceeded. Wait `Retry-After` seconds before issuing the next request."}}, "tags": ["Enrichment"], "security": [{"Bearer": []}]}, "parameters": []}, "/enrichments/score/": {"post": {"operationId": "score_products", "summary": "Score product data quality", "description": "Scores each product across Essentials, Identifiers, and Product detail using the same deterministic logic as the merchandiser dashboard. Returns per-dimension scores, an overall health score, and actionable issues. Legacy field names (agentic_commerce_score, content_quality_score, reviews_score) are still returned as aliases.", "parameters": [{"name": "data", "in": "body", "required": true, "schema": {"$ref": "#/definitions/ProductScoreBatchRequest"}}], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/ProductScoreBatchResponse"}}, "400": {"description": "Request body failed validation. `fields` enumerates the offending paths.", "examples": {"application/json": {"error": {"code": "validation_error", "message": "Request body failed validation.", "fields": {"products": ["This field is required."]}, "request_id": "8b7e2d4f3c4f4e58b6c2a1d6f0c9e1a2"}}}}, "401": {"description": "Missing or invalid API key."}, "429": {"description": "Per-key rate limit exceeded. Wait `Retry-After` seconds before issuing the next request."}}, "tags": ["Enrichment"], "security": [{"Bearer": []}]}, "parameters": []}, "/enrichments/{request_id}/": {"get": {"operationId": "get_enrichment", "summary": "Enrichment request status", "description": "Webhook delivery is the canonical channel for results, but callers can poll this endpoint to recover from missed or delayed callbacks. Returns the same status payload as the create endpoint, refreshed with the current `status` and any `error_message`.", "parameters": [{"name": "request_id", "in": "path", "description": "UUID returned by `POST /v1/enrichments`.", "required": true, "type": "string"}], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/EnrichmentRequestStatus"}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Unknown `request_id` for this API key."}, "429": {"description": "Per-key rate limit exceeded. Wait `Retry-After` seconds before issuing the next request."}}, "tags": ["Enrichment"], "security": [{"Bearer": []}]}, "parameters": [{"name": "request_id", "in": "path", "required": true, "type": "string"}]}, "/fanout/queries/": {"get": {"operationId": "list_query_fanouts", "summary": "List all Query Fan-outs", "description": "Returns all fan-out search queries generated from your tracked prompts, together with each query's usage frequency. Fan-out queries are the actual search strings Ranketta submits to AI engines to gather completions for a given prompt.", "parameters": [{"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}, {"name": "search", "in": "query", "description": "Filter query text.", "type": "string"}, {"name": "prompt_ids", "in": "query", "description": "Comma-separated prompt IDs.", "type": "string"}, {"name": "topic_ids", "in": "query", "description": "Comma-separated topic IDs.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/FanoutQuery"}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Query Fanouts"], "security": [{"Bearer": []}]}, "parameters": []}, "/merchandiser/products/": {"get": {"operationId": "list_my_products", "summary": "List My Products", "description": "Returns the products tracked in the Merchandiser module for the company. Products include their enriched attributes, override values, and last agent-run results. Supports full-text search and sorting.", "parameters": [{"name": "search", "in": "query", "description": "Free-text search across product names, SKUs, and external IDs.", "type": "string"}, {"name": "price_min", "in": "query", "description": "Minimum price (inclusive).", "type": "number"}, {"name": "price_max", "in": "query", "description": "Maximum price (inclusive).", "type": "number"}, {"name": "price_currency", "in": "query", "description": "Currency price_min/price_max are entered in (e.g. `CZK`). Defaults to `EUR`.", "type": "string"}, {"name": "availability", "in": "query", "description": "`any`, `in_stock`, or `out_of_stock`.", "type": "string"}, {"name": "category", "in": "query", "description": "Comma-separated category paths to include.", "type": "string"}, {"name": "brand_include", "in": "query", "description": "Comma-separated brand names to include.", "type": "string"}, {"name": "brand_exclude", "in": "query", "description": "Comma-separated brand names to exclude.", "type": "string"}, {"name": "tags", "in": "query", "description": "Comma-separated tags; product must have at least one.", "type": "string"}, {"name": "gtin", "in": "query", "description": "`any`, `with_gtin`, or `without_gtin`.", "type": "string"}, {"name": "enrichment_status", "in": "query", "description": "Comma-separated statuses: `enriched`, `not_enriched`, `enriching`.", "type": "string"}, {"name": "issues_min", "in": "query", "description": "Minimum issue count.", "type": "integer"}, {"name": "feed_source", "in": "query", "description": "Comma-separated feed source ids (encoded or numeric) and store ids (`store_<pk>`). Product must belong to at least one.", "type": "string"}, {"name": "ordering", "in": "query", "description": "Field to sort by, prefix with `-` for descending (e.g. `-price`).", "type": "string"}, {"name": "page", "in": "query", "description": "Page number.", "type": "integer"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/MerchandiserProductList"}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Shopping"], "security": [{"Bearer": []}]}, "parameters": []}, "/merchandiser/products/{id}/": {"get": {"operationId": "get_my_product", "summary": "My Product detail", "description": "Returns full details for a single tracked product, including its enriched attributes, accepted overrides, and visibility metrics.", "parameters": [{"name": "pk", "in": "path", "description": "Encoded product ID.", "type": "string", "required": true}], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/MerchandiserProductDetail"}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Product not found."}}, "tags": ["Shopping"], "security": [{"Bearer": []}]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/merchandiser/products/{id}/agents/run/": {"post": {"operationId": "run_product_enrichment", "summary": "Run AI enrichment on a product", "description": "Triggers an AI enrichment agent run for the specified product. The agent analyses the product and generates improvement proposals for the requested field paths. Proposals must be accepted/rejected separately.", "parameters": [{"name": "pk", "in": "path", "description": "Encoded product ID.", "type": "string", "required": true}], "responses": {"202": {"description": "Agent run started.", "schema": {"type": "object", "properties": {"runs": {"description": "List of agent run objects.", "type": "array", "items": {"type": "object"}}}}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Product not found."}}, "tags": ["Shopping"], "security": [{"Bearer": []}]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/overview/chart-data/{chart_type}/": {"get": {"operationId": "get_overview_chart_data", "summary": "Overall visibility over time", "description": "Returns a time-series data set for the specified metric across all prompts. `chart_type` must be one of: `visibility`, `sentiment`, `position`, `share_of_voice`. Supports date range and provider/country/topic/tag filtering.", "parameters": [{"name": "chart_type", "in": "path", "description": "Metric to chart: visibility | sentiment | position | share_of_voice.", "type": "string", "required": true}, {"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}, {"name": "provider_ids", "in": "query", "description": "Comma-separated AI provider IDs.", "type": "string"}, {"name": "competitor_ids", "in": "query", "description": "Comma-separated competitor IDs to show on the chart. When set, only these competitors are returned (no rank-based backfill). When omitted, the top `limit` competitors by mention rank are used.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/ShareOfVoiceChartData"}}}, "400": {"description": "Invalid chart_type."}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Overview"], "security": [{"Bearer": []}]}, "parameters": [{"name": "chart_type", "in": "path", "required": true, "type": "string"}]}, "/overview/chart-data/{chart_type}/by-provider/": {"get": {"operationId": "get_overview_chart_data_by_provider", "summary": "Visibility over time by AI model", "description": "Same as the standard chart data endpoint, but the response is segmented by AI provider so you can compare visibility or sentiment across ChatGPT, Gemini, Perplexity, etc. for the selected metric.", "parameters": [{"name": "chart_type", "in": "path", "description": "Metric to chart: visibility | sentiment | position | share_of_voice.", "type": "string", "required": true}, {"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/CustomerChartDataByProvider"}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Overview"], "security": [{"Bearer": []}]}, "parameters": [{"name": "chart_type", "in": "path", "required": true, "type": "string"}]}, "/overview/competitors/scatter/": {"get": {"operationId": "get_overview_competitor_scatter", "summary": "Competitor scatter chart data", "description": "Returns a scatter-plot dataset of top competitors with their brand visibility on the X-axis and average sentiment on the Y-axis, aggregated across all prompts. Useful for a quick competitive landscape overview.", "parameters": [{"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}, {"name": "competitor_ids", "in": "query", "description": "Comma-separated competitor IDs to show. When set, only these competitors are returned (no rank-based backfill). When omitted, the top competitors by mention rank are used.", "type": "string"}], "responses": {"200": {"description": "List of competitor scatter data points.", "schema": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "string"}, "name": {"type": "string"}, "visibility": {"type": "number"}, "sentiment": {"type": "number"}, "mention_count": {"type": "integer"}}}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Overview"], "security": [{"Bearer": []}]}, "parameters": []}, "/overview/snippets/highlights/": {"get": {"operationId": "get_overview_snippet_highlights", "summary": "Customer pos/neg snippet highlights by source domain", "description": "Customer positive/negative mention highlights, optionally by citation domain.", "parameters": [], "responses": {"200": {"description": "Snippet highlights payload"}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Sentiment"], "security": [{"Bearer": []}]}, "parameters": []}, "/overview/snippets/perception/": {"get": {"operationId": "get_overview_snippet_perception", "summary": "Head-to-head visibility/position/sentiment + snippets", "description": "Returns visibility, position, sentiment, and top positive/negative mention snippets for the customer brand, and optionally one selected competitor when `competitor` is provided.", "parameters": [], "responses": {"200": {"description": "Snippet perception payload"}, "400": {"description": "Invalid competitor."}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Sentiment"], "security": [{"Bearer": []}]}, "parameters": []}, "/overview/snippets/sentiment-over-time/": {"get": {"operationId": "get_overview_snippet_sentiment_over_time", "summary": "Customer sentiment score over time with snippet mix", "description": "Customer brand daily sentiment score + snippet severity composition.", "parameters": [], "responses": {"200": {"description": "Sentiment timeseries payload"}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Sentiment"], "security": [{"Bearer": []}]}, "parameters": []}, "/overview/snippets/source-domains/": {"get": {"operationId": "get_overview_snippet_source_domains", "summary": "Domains with customer mention snippets", "description": "Citation domains that have customer mention snippets (for Sources filter).", "parameters": [], "responses": {"200": {"description": "Source domains payload"}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Sentiment"], "security": [{"Bearer": []}]}, "parameters": []}, "/overview/stats/": {"get": {"operationId": "get_overview_stats", "summary": "Overall visibility statistics", "description": "Returns aggregated share-of-voice, visibility, sentiment and position statistics across all tracked prompts for the company. Supports optional date range and filtering by provider, country, topic or tag.", "parameters": [{"name": "start_date", "in": "query", "description": "ISO 8601 start date (YYYY-MM-DD).", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date (YYYY-MM-DD).", "type": "string"}, {"name": "provider_ids", "in": "query", "description": "Comma-separated AI provider IDs to filter by.", "type": "string"}, {"name": "topic_ids", "in": "query", "description": "Comma-separated topic IDs to filter by.", "type": "string"}, {"name": "tag_ids", "in": "query", "description": "Comma-separated tag IDs to filter by.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/ShareOfVoiceStats"}}, "401": {"description": "Missing or invalid API key."}, "403": {"description": "Access denied."}}, "tags": ["Overview"], "security": [{"Bearer": []}]}, "parameters": []}, "/prompt/all/": {"get": {"operationId": "list_prompts", "summary": "List tracked prompts", "description": "Returns all prompts tracked for the company. Each prompt represents a question or query that Ranketta monitors across AI search engines. Results include the prompt's visibility score, sentiment, and last-run timestamp.", "parameters": [{"name": "search", "in": "query", "description": "Filter by prompt text.", "type": "string"}, {"name": "topic_ids", "in": "query", "description": "Comma-separated topic IDs to filter by.", "type": "string"}, {"name": "tag_ids", "in": "query", "description": "Comma-separated tag IDs to filter by.", "type": "string"}, {"name": "page", "in": "query", "description": "Page number (pagination optional).", "type": "integer"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/PromptList"}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Prompts"], "security": [{"Bearer": []}]}, "parameters": []}, "/prompt/countries/": {"get": {"operationId": "list_prompt_countries", "summary": "Countries with active prompts", "description": "Returns the countries for which your workspace has active prompts. Optionally filter by prompt, topic, or tag IDs. Use the returned IDs as `country_ids` filter values when calling analytics or chart endpoints.", "parameters": [{"name": "prompt_ids", "in": "query", "description": "Filter by encoded prompt IDs.", "type": "array", "items": {"type": "string"}}, {"name": "topic_ids", "in": "query", "description": "Filter by encoded topic IDs.", "type": "array", "items": {"type": "string"}}, {"name": "tag_ids", "in": "query", "description": "Filter by encoded tag IDs.", "type": "array", "items": {"type": "string"}}], "responses": {"200": {"description": "List of countries.", "schema": {"type": "object", "properties": {"countries": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "integer"}, "code": {"type": "string"}, "name": {"type": "string"}, "flag_emoji": {"type": "string"}}}}}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Reference"], "security": [{"Bearer": []}]}, "parameters": []}, "/prompt/create/": {"post": {"operationId": "create_prompts", "summary": "Create one or more prompts", "description": "Creates one or more tracked prompts from an array of prompt texts. Ranketta will start monitoring each prompt across AI search engines on the next scheduled crawl.", "parameters": [], "responses": {"201": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/Prompt"}}}, "400": {"description": "Validation error."}, "401": {"description": "Missing or invalid API key."}, "402": {"description": "Prompt quota exceeded."}}, "tags": ["Prompts"], "security": [{"Bearer": []}]}, "parameters": []}, "/prompt/import/csv/": {"post": {"operationId": "import_prompts_csv", "summary": "Import prompts from a CSV file", "description": "Accepts a multipart upload of a single-column CSV file where each row is a prompt text. Duplicate prompts are skipped. Returns a summary of how many prompts were created, skipped, and failed.", "parameters": [], "responses": {"201": {"description": "Import result summary.", "schema": {"type": "object", "properties": {"created": {"description": "List of created prompt objects.", "type": "array", "items": {"type": "object"}}, "count": {"description": "Number of prompts created in this import.", "type": "integer"}, "total_rows": {"type": "integer"}, "unique_rows": {"type": "integer"}, "duplicates_collapsed": {"type": "integer"}}}}, "400": {"description": "Invalid file or format."}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Prompts"], "security": [{"Bearer": []}]}, "parameters": []}, "/prompt/responses/": {"get": {"operationId": "list_overall_responses", "summary": "AI model responses across all prompts", "description": "Returns the raw AI completions collected across all prompts for the active company/website, together with structured data: which competitors were mentioned, the cited URLs, own-brand sentiment, and the AI provider that generated the response.", "parameters": [{"name": "search", "in": "query", "description": "Search string to filter response text.", "type": "string"}, {"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}, {"name": "provider_ids", "in": "query", "description": "Comma-separated provider IDs to filter by.", "type": "string"}, {"name": "topic_ids", "in": "query", "description": "Comma-separated topic IDs.", "type": "string"}, {"name": "country_ids", "in": "query", "description": "Comma-separated country IDs.", "type": "string"}, {"name": "tag_ids", "in": "query", "description": "Comma-separated prompt tag IDs.", "type": "string"}, {"name": "competitor_ids", "in": "query", "description": "Comma-separated competitor IDs to filter by (only responses mentioning these competitors).", "type": "string"}, {"name": "mentioned", "in": "query", "description": "Filter by whether the customer's own brand was mentioned: true/false. Omit or 'all' for no filter.", "type": "string"}, {"name": "cited", "in": "query", "description": "Filter by whether the company's own website domain was cited: true/false. Omit or 'all' for no filter.", "type": "string"}, {"name": "snippet_sentiment", "in": "query", "description": "Filter by severity of any competitor mention snippets: positive or negative. Omit for no filter.", "type": "string"}, {"name": "has_ad", "in": "query", "description": "Filter by whether a ChatGPT ad appeared: true/false. Omit or 'all' for no filter.", "type": "string"}, {"name": "has_websearch", "in": "query", "description": "Filter by whether the model ran web search / query fan-outs: true/false. Omit or 'all' for no filter.", "type": "string"}, {"name": "has_shopping", "in": "query", "description": "Filter by whether shopping products were mentioned: true/false. Omit or 'all' for no filter.", "type": "string"}, {"name": "sort_by", "in": "query", "description": "Sort field: queried_at, sentiment_score, citations_count, mention_position, llm_provider_name, mentioned, competitor_mentions.", "type": "string"}, {"name": "sort_order", "in": "query", "description": "Sort order: asc or desc.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/CompletionOverall"}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Prompts"], "security": [{"Bearer": []}]}, "parameters": []}, "/prompt/{prompt_id}/chart-data/{chart_type}/": {"get": {"operationId": "get_prompt_chart_data", "summary": "Visibility over time for a prompt", "description": "Returns a time-series dataset for the specified metric and prompt. `chart_type` must be one of: `visibility`, `sentiment`, `position`, `share_of_voice`.", "parameters": [{"name": "prompt_id", "in": "path", "description": "Encoded prompt ID.", "type": "string", "required": true}, {"name": "chart_type", "in": "path", "description": "Metric: visibility | sentiment | position | share_of_voice.", "type": "string", "required": true}, {"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/ShareOfVoiceChartData"}}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Prompt not found."}}, "tags": ["Prompts"], "security": [{"Bearer": []}]}, "parameters": [{"name": "prompt_id", "in": "path", "required": true, "type": "string"}, {"name": "chart_type", "in": "path", "required": true, "type": "string"}]}, "/prompt/{prompt_id}/citations/urls/": {"get": {"operationId": "list_prompt_citation_urls", "summary": "Citations for a prompt", "description": "Returns the specific URLs cited in AI responses for the specified prompt, with tracking parameters stripped and each URL's citation share percentage.", "parameters": [{"name": "prompt_id", "in": "path", "description": "Encoded prompt ID.", "type": "string", "required": true}, {"name": "start_date", "in": "query", "description": "ISO 8601 start date. Defaults to 30 days before today if omitted.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date. Defaults to today if omitted.", "type": "string"}, {"name": "search", "in": "query", "description": "Filter by URL.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/SourceAggregate"}}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Prompt not found."}}, "tags": ["Prompts"], "security": [{"Bearer": []}]}, "parameters": [{"name": "prompt_id", "in": "path", "required": true, "type": "string"}]}, "/prompt/{prompt_id}/competitors/": {"get": {"operationId": "list_prompt_competitors", "summary": "List competitors for a prompt", "description": "Returns all brands and domains mentioned alongside yours in AI responses for the specified prompt. Each competitor entry includes its mention count, share-of-voice percentage, and average sentiment.", "parameters": [{"name": "prompt_id", "in": "path", "description": "Encoded prompt ID.", "type": "string", "required": true}, {"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/TrackedCompanyMetric"}}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Prompt not found."}}, "tags": ["Prompts"], "security": [{"Bearer": []}]}, "parameters": [{"name": "prompt_id", "in": "path", "required": true, "type": "string"}]}, "/prompt/{prompt_id}/completions/": {"get": {"operationId": "list_prompt_completions", "summary": "AI model responses for a prompt", "description": "Returns the raw AI completions collected for the specified prompt, together with structured data: which competitors were mentioned, the cited URLs, and the AI provider that generated the response.", "parameters": [{"name": "prompt_id", "in": "path", "description": "Encoded prompt ID.", "type": "string", "required": true}, {"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}, {"name": "provider_ids", "in": "query", "description": "Comma-separated provider IDs to filter by.", "type": "string"}, {"name": "mentioned", "in": "query", "description": "Filter by whether the customer's own brand was mentioned: true/false. Omit or 'all' for no filter.", "type": "string"}, {"name": "cited", "in": "query", "description": "Filter by whether the company's own website domain was cited: true/false. Omit or 'all' for no filter.", "type": "string"}, {"name": "snippet_sentiment", "in": "query", "description": "Filter by severity of any competitor mention snippets: positive or negative. Omit for no filter.", "type": "string"}, {"name": "has_ad", "in": "query", "description": "Filter by whether a ChatGPT ad appeared: true/false. Omit or 'all' for no filter.", "type": "string"}, {"name": "has_websearch", "in": "query", "description": "Filter by whether the model ran web search / query fan-outs: true/false. Omit or 'all' for no filter.", "type": "string"}, {"name": "has_shopping", "in": "query", "description": "Filter by whether shopping products were mentioned: true/false. Omit or 'all' for no filter.", "type": "string"}, {"name": "sort_by", "in": "query", "description": "Sort field: queried_at, sentiment_score, citations_count, mention_position, llm_provider_name, mentioned, cited, competitor_mentions.", "type": "string"}, {"name": "sort_order", "in": "query", "description": "Sort order: asc or desc.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/CompletionWithMentions"}}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Prompt not found."}}, "tags": ["Prompts"], "security": [{"Bearer": []}]}, "parameters": [{"name": "prompt_id", "in": "path", "required": true, "type": "string"}]}, "/prompt/{prompt_id}/search-queries/": {"get": {"operationId": "list_prompt_search_queries", "summary": "Query Fan-outs for a prompt", "description": "Returns the fan-out search queries generated from the specified prompt, each with its usage frequency. These are the exact strings submitted to AI engines when monitoring this prompt.", "parameters": [{"name": "prompt_id", "in": "path", "description": "Encoded prompt ID.", "type": "string", "required": true}, {"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/SearchQueryFrequency"}}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Prompt not found."}}, "tags": ["Prompts"], "security": [{"Bearer": []}]}, "parameters": [{"name": "prompt_id", "in": "path", "required": true, "type": "string"}]}, "/prompt/{prompt_id}/stats/": {"get": {"operationId": "get_prompt_stats", "summary": "Visibility statistics for a prompt", "description": "Returns share-of-voice, visibility score, average position and sentiment statistics for a specific prompt, optionally filtered by date range, provider and country.", "parameters": [{"name": "prompt_id", "in": "path", "description": "Encoded prompt ID.", "type": "string", "required": true}, {"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/ShareOfVoiceStats"}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Prompt not found."}}, "tags": ["Prompts"], "security": [{"Bearer": []}]}, "parameters": [{"name": "prompt_id", "in": "path", "required": true, "type": "string"}]}, "/providers/": {"get": {"operationId": "list_ai_providers", "summary": "All AI models", "description": "Returns all active AI models tracked by Ranketta. Use the returned IDs as `provider_ids` filter values across analytics, chart data, citations, and Query Fan-out endpoints.", "parameters": [], "responses": {"200": {"description": "List of providers.", "schema": {"type": "object", "properties": {"providers": {"type": "array", "items": {"type": "object", "properties": {"id": {"type": "integer"}, "name": {"type": "string"}, "code": {"type": "string"}, "monthly_queries": {"type": "integer"}, "shopping_enabled": {"type": "boolean"}}}}}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Reference"], "security": [{"Bearer": []}]}, "parameters": []}, "/shopping/overview/brands/scatter/": {"get": {"operationId": "get_shopping_brand_scatter", "summary": "Brand purchase likelihood scatter", "description": "Returns a scatter-plot dataset of brands with their recommendation share on the X-axis and average position on the Y-axis. Useful for spotting which brands dominate AI shopping recommendations.", "parameters": [{"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}], "responses": {"200": {"description": "Brand scatter data points.", "schema": {"type": "array", "items": {"type": "object", "properties": {"id": {"description": "Encoded brand ID.", "type": "string"}, "name": {"type": "string"}, "share_of_voice": {"description": "Recommendation share (0–1).", "type": "number"}, "average_position": {"type": "number"}}}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Shopping"], "security": [{"Bearer": []}]}, "parameters": []}, "/shopping/overview/chart-data/{chart_type}/": {"get": {"operationId": "get_shopping_overview_chart", "summary": "Shopping overview chart data", "description": "Returns time-series chart data for shopping visibility metrics. `chart_type` controls the entity and metric: e.g. `brand_share_of_voice`, `vendor_share_of_voice`, `brand_visibility`, `vendor_visibility`.", "parameters": [{"name": "chart_type", "in": "path", "description": "Type of shopping chart to return.", "type": "string", "required": true}, {"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}, {"name": "prompt_ids", "in": "query", "description": "Comma-separated prompt IDs.", "type": "string"}], "responses": {"200": {"description": "Shopping chart data.", "schema": {"type": "object", "properties": {"chart_data": {"type": "array", "items": {"type": "object", "properties": {"date": {"description": "ISO 8601 date.", "type": "string"}, "value": {"type": "number"}}}}, "benchmarks": {"type": "array", "items": {"type": "object"}}}}}, "400": {"description": "Invalid chart_type."}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Shopping"], "security": [{"Bearer": []}]}, "parameters": [{"name": "chart_type", "in": "path", "required": true, "type": "string"}]}, "/shopping/overview/stats/": {"get": {"operationId": "get_shopping_overview_stats", "summary": "Brand & vendor visibility statistics", "description": "Returns aggregated statistics for AI-driven shopping visibility: total recommended products, top brands, top vendors, and overall recommendation share across all tracked prompts.", "parameters": [{"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}], "responses": {"200": {"description": "Shopping overview statistics.", "schema": {"type": "object", "properties": {"brand_visibility": {"description": "Brand visibility score (0–1).", "type": "number"}, "brand_position": {"description": "Average brand position.", "type": "number"}, "brand_sentiment": {"description": "Brand sentiment score (0–100).", "type": "number"}, "vendor_visibility": {"type": "number"}, "vendor_share_of_voice": {"type": "number"}, "brand_visibility_variation": {"type": "number", "x-nullable": true}, "brand_position_variation": {"type": "number", "x-nullable": true}, "brand_sentiment_variation": {"type": "number", "x-nullable": true}, "vendor_visibility_variation": {"type": "number", "x-nullable": true}, "vendor_share_of_voice_variation": {"type": "number", "x-nullable": true}}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Shopping"], "security": [{"Bearer": []}]}, "parameters": []}, "/shopping/products/": {"get": {"operationId": "list_shopping_products", "summary": "List products recommended by AI", "description": "Returns all products that AI models have recommended in response to your tracked prompts. Each product includes vendor offers, brand, and a recommendation share (percentage of completions in which it appeared).", "parameters": [{"name": "start_date", "in": "query", "description": "ISO 8601 start date.", "type": "string"}, {"name": "end_date", "in": "query", "description": "ISO 8601 end date.", "type": "string"}, {"name": "prompt_ids", "in": "query", "description": "Comma-separated prompt IDs to filter by.", "type": "string"}, {"name": "search", "in": "query", "description": "Filter by product name or brand.", "type": "string"}], "responses": {"200": {"description": "Paginated list of recommended products.", "schema": {"type": "object", "properties": {"count": {"type": "integer"}, "next": {"type": "string", "x-nullable": true}, "previous": {"type": "string", "x-nullable": true}, "total_completions": {"description": "Total number of AI completions analysed.", "type": "integer"}, "results": {"type": "array", "items": {"type": "object", "properties": {"id": {"description": "Encoded product ID.", "type": "string"}, "title": {"type": "string"}, "brand": {"type": "string"}, "visibility": {"description": "Share-of-voice (0–1).", "type": "number"}, "average_position": {"type": "number"}, "recommendation_count": {"type": "integer"}}}}}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Shopping"], "security": [{"Bearer": []}]}, "parameters": []}, "/site-audit/": {"get": {"operationId": "list_site_audits", "summary": "List site audits", "description": "Returns all site audits performed for the company, newest first. Each audit record includes the crawled domain, status, page count and timestamps.", "parameters": [], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/SiteAuditList"}}}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Site Audit"], "security": [{"Bearer": []}]}, "parameters": []}, "/site-audit/analyze-page/": {"post": {"operationId": "analyze_site_audit_page", "summary": "Analyze a single page", "description": "Crawls and analyzes a single URL on demand. Runs a full SEO and AI-readiness analysis via Crawl4AI and returns the resulting audit and page IDs. Optionally attaches the page to an existing manual audit.", "parameters": [], "responses": {"200": {"description": "Analysis result.", "schema": {"type": "object", "properties": {"audit_id": {"description": "Encoded audit ID.", "type": "string"}, "page_id": {"description": "Encoded page ID.", "type": "string"}, "url": {"description": "Analyzed URL.", "type": "string"}, "overall_score": {"type": "number"}}}}, "400": {"description": "Missing or invalid URL."}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Site Audit"], "security": [{"Bearer": []}]}, "parameters": []}, "/site-audit/start/": {"post": {"operationId": "start_site_audit", "summary": "Start a new site audit", "description": "Starts a full automated crawl and SEO/AI-readiness audit for the given domain. The crawl runs asynchronously; poll the list or detail endpoints to check progress.", "parameters": [], "responses": {"201": {"description": "", "schema": {"$ref": "#/definitions/SiteAudit"}}, "400": {"description": "Missing or invalid domain."}, "401": {"description": "Missing or invalid API key."}}, "tags": ["Site Audit"], "security": [{"Bearer": []}]}, "parameters": []}, "/site-audit/{id}/pages/": {"get": {"operationId": "list_site_audit_pages", "summary": "List pages in a site audit", "description": "Returns all crawled pages for the specified site audit, with their SEO scores, performance metrics, and AI-readiness ratings.", "parameters": [{"name": "pk", "in": "path", "description": "Encoded site audit ID.", "type": "string", "required": true}, {"name": "search", "in": "query", "description": "Filter pages by URL.", "type": "string"}, {"name": "sort_by", "in": "query", "description": "Sort field: overall_score, img_alt_tags_score, technical_seo_score, content_quality_score, aeo_score, issues.", "type": "string"}, {"name": "sort_order", "in": "query", "description": "Sort direction: asc or desc.", "type": "string"}], "responses": {"200": {"description": "", "schema": {"type": "array", "items": {"$ref": "#/definitions/SiteAuditPage"}}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Audit not found."}}, "tags": ["Site Audit"], "security": [{"Bearer": []}]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/site-audit/{id}/stats/": {"get": {"operationId": "get_site_audit_stats", "summary": "Site audit summary statistics", "description": "Returns aggregate statistics for the specified site audit: total pages crawled, average SEO score, number of issues found by severity, and AI-readiness breakdown.", "parameters": [{"name": "pk", "in": "path", "description": "Encoded site audit ID.", "type": "string", "required": true}], "responses": {"200": {"description": "Audit statistics object.", "schema": {"type": "object", "properties": {"technical_seo": {"description": "Average technical SEO score (0–100).", "type": "number"}, "content_quality": {"description": "Average content quality score (0–100).", "type": "number"}, "aeo_score": {"description": "Average AI-readiness score (0–100).", "type": "number"}, "pages_count": {"description": "Total number of crawled pages.", "type": "integer"}}}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Audit not found."}}, "tags": ["Site Audit"], "security": [{"Bearer": []}]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}, "/site-audit/{id}/stop/": {"post": {"operationId": "stop_site_audit", "summary": "Stop a running site audit", "description": "Revokes the background crawl task for the specified audit and marks it as cancelled. Already-crawled pages are preserved.", "parameters": [{"name": "pk", "in": "path", "description": "Encoded site audit ID.", "type": "string", "required": true}], "responses": {"200": {"description": "", "schema": {"$ref": "#/definitions/SiteAudit"}}, "401": {"description": "Missing or invalid API key."}, "404": {"description": "Audit not found."}}, "tags": ["Site Audit"], "security": [{"Bearer": []}]}, "parameters": [{"name": "id", "in": "path", "required": true, "type": "string"}]}}, "definitions": {"SourceAggregate": {"required": ["id", "type", "source_url", "domain", "citation_count", "citation_percentage", "prompt_count", "latest_citation_date", "latest_citation"], "type": "object", "properties": {"id": {"title": "Id", "type": "string", "minLength": 1}, "type": {"title": "Type", "type": "string", "enum": ["domain", "source"]}, "source_url": {"title": "Source url", "type": "string", "format": "uri", "minLength": 1, "x-nullable": true}, "display_url": {"title": "Display url", "description": "Human-friendly URL for UI display (scheme and www. stripped). Null for domain rows.", "type": "string", "minLength": 1, "x-nullable": true}, "domain": {"title": "Domain", "type": "string", "minLength": 1}, "favicon_url": {"title": "Favicon url", "type": "string", "format": "uri", "minLength": 1, "x-nullable": true}, "domain_type": {"title": "Domain type", "type": "string", "minLength": 1, "x-nullable": true}, "domain_types": {"type": "array", "items": {"type": "string", "minLength": 1}}, "page_type": {"title": "Page type", "type": "string", "minLength": 1, "x-nullable": true}, "page_types": {"type": "array", "items": {"type": "string", "minLength": 1}}, "citation_count": {"title": "Citation count", "type": "integer"}, "citation_percentage": {"title": "Citation percentage", "description": "Usage rate: percentage of completions that used this domain/URL", "type": "number"}, "citation_percentage_variation": {"title": "Citation percentage variation", "description": "Change in citation_percentage from previous period (current - previous)", "type": "number", "x-nullable": true}, "prompt_count": {"title": "Prompt count", "type": "integer", "x-nullable": true}, "latest_citation_date": {"title": "Latest citation date", "type": "string", "format": "date-time", "x-nullable": true}, "latest_citation": {"title": "Latest citation", "type": "string", "minLength": 1, "x-nullable": true}, "title": {"title": "Title", "description": "Title from citation, or null if not available", "type": "string", "minLength": 1, "x-nullable": true}, "mentioned": {"title": "Mentioned", "type": "boolean", "default": false}, "mentions_loading": {"title": "Mentions loading", "type": "boolean", "default": false}, "customer_mention_status": {"title": "Customer mention status", "type": "string", "enum": ["loading", "mentioned", "not_mentioned"]}, "source_count": {"title": "Source count", "type": "integer", "x-nullable": true}, "http_status_code": {"title": "Http status code", "type": "integer", "x-nullable": true}, "providers": {"type": "array", "items": {"type": "object", "additionalProperties": {"type": "string", "minLength": 1}}, "default": [], "x-nullable": true}, "citations": {"title": "Citations", "type": "string", "readOnly": true}}}, "ContentList": {"required": ["content_type", "company"], "type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "title": {"title": "Title", "description": "Title of the content", "type": "string", "maxLength": 500}, "content_type": {"title": "Content type", "description": "Type of content", "type": "integer"}, "content_type_name": {"title": "Content type name", "type": "string", "readOnly": true, "minLength": 1}, "content_type_icon": {"title": "Content type icon", "type": "string", "readOnly": true, "minLength": 1}, "status": {"title": "Status", "description": "Current status of the content", "type": "string", "enum": ["generating", "draft", "completed", "exported"]}, "language": {"title": "Language", "description": "Language of the content (set during configuration)", "type": "integer", "x-nullable": true}, "source_url": {"title": "Source url", "description": "Original URL if content was imported from URL", "type": "string", "format": "uri", "maxLength": 2048, "x-nullable": true}, "prompt_ids": {"title": "Prompt ids", "type": "string", "readOnly": true}, "topic_ids": {"title": "Topic ids", "type": "string", "readOnly": true}, "provider_ids": {"title": "Provider ids", "type": "string", "readOnly": true}, "provider_codes": {"title": "Provider codes", "type": "string", "readOnly": true}, "citations_count": {"title": "Citations count", "type": "string", "readOnly": true}, "all_keywords": {"title": "All keywords", "type": "string", "readOnly": true}, "company": {"title": "Company", "description": "Company this content belongs to", "type": "integer"}, "created_by": {"title": "Created by", "type": "string", "readOnly": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}}}, "ContentType": {"required": ["name"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "name": {"title": "Name", "description": "Display name of the content type (e.g., 'Comparison', 'How To', 'Review')", "type": "string", "maxLength": 100, "minLength": 1}, "icon": {"title": "Icon", "description": "Icon class name for the content type (e.g., 'i-lucide-scale', 'i-lucide-help-circle')", "type": "string", "maxLength": 100}, "description": {"title": "Description", "description": "Short description shown on content type cards in the app.", "type": "string", "x-nullable": true}, "custom_instructions": {"title": "Custom instructions", "description": "Custom instructions for generating this type of content. These instructions will be included in the prompt sent to the AI model. Example: 'Focus on comparing features side-by-side. Include pros and cons for each option.'", "type": "string"}, "is_active": {"title": "Is active", "description": "Whether this content type is active and can be used", "type": "boolean"}, "content_count": {"title": "Content count", "type": "integer", "readOnly": true}, "has_custom_instructions": {"title": "Has custom instructions", "type": "boolean", "readOnly": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}}}, "ContentGeneration": {"required": ["model_name"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "content": {"title": "Content", "description": "Content being generated", "type": "integer", "readOnly": true}, "content_title": {"title": "Content title", "type": "string", "readOnly": true, "minLength": 1}, "provider": {"title": "Provider", "description": "AI provider used for generation", "type": "string", "enum": ["gemini", "openai", "anthropic", "perplexity", "other"]}, "model_name": {"title": "Model name", "description": "Specific model used (e.g., gemini-pro, gpt-4)", "type": "string", "maxLength": 255, "minLength": 1}, "status": {"title": "Status", "description": "Status of the generation", "type": "string", "enum": ["pending", "in_progress", "completed", "failed"]}, "operation_type": {"title": "Operation type", "description": "Type of operation", "type": "string", "enum": ["generation", "optimization", "editing", "other"]}, "is_active": {"title": "Is active", "description": "Whether this generation is the active/current version", "type": "boolean"}, "content_html": {"title": "Content html", "description": "Generated content in HTML format (extracted from response)", "type": "string"}, "input_tokens": {"title": "Input tokens", "description": "Number of input tokens used", "type": "integer", "maximum": 2147483647, "minimum": 0}, "output_tokens": {"title": "Output tokens", "description": "Number of output tokens generated", "type": "integer", "maximum": 2147483647, "minimum": 0}, "cached_input_tokens": {"title": "Cached input tokens", "description": "Number of cached input tokens (if applicable)", "type": "integer", "maximum": 2147483647, "minimum": 0}, "total_tokens": {"title": "Total tokens", "type": "integer", "readOnly": true}, "cost_usd": {"title": "Cost usd", "description": "Cost in USD for this generation", "type": "string", "x-nullable": true}, "credits_charged": {"title": "Credits charged", "description": "Customer credits charged for this generation", "type": "integer", "maximum": 2147483647, "minimum": 0}, "error_message": {"title": "Error message", "description": "Error message if generation failed", "type": "string"}, "retry_count": {"title": "Retry count", "description": "Number of retry attempts", "type": "integer", "maximum": 2147483647, "minimum": 0}, "started_at": {"title": "Started at", "description": "When generation started", "type": "string", "format": "date-time", "x-nullable": true}, "completed_at": {"title": "Completed at", "description": "When generation completed", "type": "string", "format": "date-time", "x-nullable": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}}}, "ContentRecommendation": {"required": ["type", "title", "description"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "content": {"title": "Content", "description": "Content this recommendation is for", "type": "integer", "readOnly": true}, "type": {"title": "Type", "description": "Type of recommendation", "type": "string", "enum": ["keyword", "topic", "search_query", "content_improvement"]}, "title": {"title": "Title", "description": "Short title/description of the recommendation", "type": "string", "maxLength": 255, "minLength": 1}, "description": {"title": "Description", "description": "Detailed description of the recommendation", "type": "string", "minLength": 1}, "search_query": {"title": "Search query", "description": "Recommended search query/keyword (if type is keyword or search_query)", "type": "integer", "x-nullable": true}, "search_query_text": {"title": "Search query text", "type": "string", "readOnly": true, "minLength": 1, "x-nullable": true}, "topic": {"title": "Topic", "description": "Recommended topic (if type is topic)", "type": "integer", "x-nullable": true}, "topic_name": {"title": "Topic name", "type": "string", "readOnly": true, "minLength": 1, "x-nullable": true}, "status": {"title": "Status", "description": "Status of the recommendation", "type": "string", "enum": ["proposed", "accepted", "rejected", "implemented"]}, "score": {"title": "Score", "description": "Relevance score (0-1) for this recommendation", "type": "number", "x-nullable": true}, "source": {"title": "Source", "description": "Source of the recommendation (e.g., 'research', 'ai', 'manual')", "type": "string", "maxLength": 50}, "metadata": {"title": "Metadata", "description": "Additional metadata about the recommendation", "type": "object"}, "created_by": {"title": "Created by", "type": "string", "readOnly": true}, "accepted_by": {"title": "Accepted by", "type": "string", "readOnly": true}, "accepted_at": {"title": "Accepted at", "description": "When the recommendation was accepted", "type": "string", "format": "date-time", "x-nullable": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}}}, "ContentVersion": {"type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "content": {"title": "Content", "description": "Content this version belongs to", "type": "integer", "readOnly": true}, "version_number": {"title": "Version number", "description": "Sequential version number for this content", "type": "integer", "readOnly": true}, "content_html": {"title": "Content html", "description": "Content snapshot at this version", "type": "string"}, "change_type": {"title": "Change type", "description": "Type of change that created this version", "type": "string", "enum": ["manual", "ai_generation", "ai_optimization", "ai_editing", "import", "restore"]}, "change_description": {"title": "Change description", "description": "Human-readable description of what changed in this version", "type": "string"}, "created_by": {"title": "Created by", "type": "string", "readOnly": true}, "created_by_name": {"title": "Created by name", "type": "string", "readOnly": true, "minLength": 1, "x-nullable": true}, "created_by_email": {"title": "Created by email", "type": "string", "readOnly": true, "minLength": 1, "x-nullable": true}, "created_by_color": {"title": "Created by color", "type": "string", "readOnly": true}, "generation": {"title": "Generation", "description": "ContentGeneration that created this version (if AI-generated)", "type": "integer", "x-nullable": true}, "generation_provider": {"title": "Generation provider", "type": "string", "readOnly": true, "minLength": 1, "x-nullable": true}, "generation_model": {"title": "Generation model", "type": "string", "readOnly": true, "minLength": 1, "x-nullable": true}, "generation_operation_type": {"title": "Generation operation type", "type": "string", "readOnly": true, "minLength": 1, "x-nullable": true}, "metadata": {"title": "Metadata", "description": "Additional metadata about this version", "type": "object"}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}}}, "ContentCitation": {"required": ["content", "title", "source_url"], "type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "content": {"title": "Content", "description": "Content this citation is associated with", "type": "integer"}, "citation": {"title": "Citation", "description": "The citation from a completion (only for calculated citations)", "type": "integer", "x-nullable": true}, "title": {"title": "Title", "description": "Title/description of the citation", "type": "string", "maxLength": 10485760, "minLength": 1}, "source_url": {"title": "Source url", "description": "The URL of the citation", "type": "string", "format": "uri", "maxLength": 2000, "minLength": 1}, "domain": {"title": "Domain", "description": "Domain extracted from the source URL", "type": "string", "maxLength": 255}, "meta": {"title": "Meta", "description": "Meta description or excerpt from the page", "type": "string", "maxLength": 10485760, "x-nullable": true}, "favicon_url": {"title": "Favicon url", "description": "The URL of the favicon", "type": "string", "format": "uri", "maxLength": 2000, "x-nullable": true}, "source": {"title": "Source", "description": "How this citation was added to the content", "type": "string", "enum": ["calculated", "manual"]}, "citation_count": {"title": "Citation count", "description": "Number of times this citation appeared across selected completions (for calculated citations)", "type": "integer", "maximum": 2147483647, "minimum": 0}, "citation_share": {"title": "Citation share", "description": "Percentage share of total citations (0-100, for calculated citations)", "type": "number", "x-nullable": true}, "rank": {"title": "Rank", "description": "Rank position among all citations (1 = most cited, for calculated citations)", "type": "integer", "maximum": 2147483647, "minimum": 0, "x-nullable": true}, "is_selected": {"title": "Is selected", "description": "Whether this citation is selected for content generation", "type": "boolean"}, "added_by": {"title": "Added by", "type": "string", "readOnly": true}, "added_by_name": {"title": "Added by name", "type": "string", "readOnly": true, "minLength": 1, "x-nullable": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}}}, "ContentKeyword": {"type": "object", "properties": {"id": {"title": "ID", "type": "integer", "readOnly": true}, "search_query": {"title": "Search query", "description": "Fan-out SearchQuery when linked to analytics data; null for custom text only", "type": "integer", "readOnly": true, "x-nullable": true}, "search_query_id": {"title": "Search query id", "type": "string", "readOnly": true}, "search_query_text": {"title": "Search query text", "type": "string", "readOnly": true}, "custom_query_text": {"title": "Custom query text", "description": "User-defined keyword text when not using a SearchQuery FK", "type": "string", "x-nullable": true}, "source": {"title": "Source", "description": "How this keyword was added to the content", "type": "string", "enum": ["manual", "topic", "prompt", "research", "recommendation", "fanout"]}, "rank": {"title": "Rank", "description": "Order among calculated fan-out keywords (1 = highest usage rate)", "type": "integer", "readOnly": true, "x-nullable": true}, "usage_rate": {"title": "Usage rate", "description": "Share of completions using this query among selected completions (0–100)", "type": "number", "readOnly": true, "x-nullable": true}, "is_selected": {"title": "Is selected", "description": "Whether this keyword is selected for content generation", "type": "boolean"}, "added_by": {"title": "Added by", "type": "string", "readOnly": true}, "added_at": {"title": "Added at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}}}, "Content": {"required": ["content_type"], "type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "title": {"title": "Title", "description": "Title of the content", "type": "string", "maxLength": 500}, "content_type": {"title": "Content type", "description": "Type of content", "type": "integer"}, "content_type_details": {"$ref": "#/definitions/ContentType"}, "content_type_name": {"title": "Content type name", "type": "string", "readOnly": true, "minLength": 1}, "content_type_icon": {"title": "Content type icon", "type": "string", "readOnly": true, "minLength": 1}, "all_keywords": {"title": "All keywords", "type": "string", "readOnly": true}, "tone_of_voice": {"title": "Tone of voice", "description": "Tone of voice settings (e.g., {'style': 'authoritative', 'tone': 'professional'})", "type": "object"}, "content_html": {"title": "Content html", "description": "Content in HTML format", "type": "string"}, "status": {"title": "Status", "description": "Current status of the content", "type": "string", "enum": ["generating", "draft", "completed", "exported"]}, "company": {"title": "Company", "description": "Company this content belongs to", "type": "integer", "readOnly": true}, "language": {"title": "Language", "description": "Language of the content (set during configuration)", "type": "integer", "x-nullable": true}, "source_url": {"title": "Source url", "description": "Original URL if content was imported from URL", "type": "string", "format": "uri", "maxLength": 2048, "x-nullable": true}, "title_suggestions": {"title": "Title suggestions", "description": "AI-generated title suggestions (e.g., {'suggestions': ['title1', ...], 'generated_at': '...'})", "type": "object", "x-nullable": true}, "created_by": {"title": "Created by", "type": "string", "readOnly": true}, "generations": {"type": "array", "items": {"$ref": "#/definitions/ContentGeneration"}, "readOnly": true}, "recommendations": {"type": "array", "items": {"$ref": "#/definitions/ContentRecommendation"}, "readOnly": true}, "versions": {"type": "array", "items": {"$ref": "#/definitions/ContentVersion"}, "readOnly": true}, "content_citations": {"type": "array", "items": {"$ref": "#/definitions/ContentCitation"}, "readOnly": true}, "content_keywords": {"type": "array", "items": {"$ref": "#/definitions/ContentKeyword"}, "readOnly": true}, "prompt_ids": {"title": "Prompt ids", "type": "string", "readOnly": true}, "prompt_ids_write": {"description": "List of Prompt IDs (hash or int) to associate with this content", "type": "array", "items": {"type": "string", "minLength": 1}}, "provider_ids": {"title": "Provider ids", "type": "string", "readOnly": true}, "citations_limit": {"title": "Citations limit", "description": "Number of top citations to include (e.g., 5, 10, 20)", "type": "integer", "maximum": 100, "minimum": 1, "x-nullable": true}, "keywords_limit": {"title": "Keywords limit", "description": "Number of top query fan-out keywords to include (e.g., 5, 10, 20)", "type": "integer", "maximum": 100, "minimum": 1, "x-nullable": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}}}, "EnrichmentRequestStatus": {"required": ["run_id", "product_id"], "type": "object", "properties": {"request_id": {"title": "Request id", "description": "UUID echoed in webhook headers and surfaced to callers.", "type": "string", "readOnly": true, "minLength": 1}, "run_id": {"title": "Run id", "description": "Internal `AgentRun` id. Useful for support tickets.", "type": "integer", "x-nullable": true}, "product_id": {"title": "Product id", "description": "The `product_id` you supplied when creating the request.", "type": "string"}, "callback_url": {"title": "Callback url", "description": "Effective callback URL used for this request (per-request override or fall back to the API key default).", "type": "string", "format": "uri", "readOnly": true, "minLength": 1}, "status": {"title": "Status", "type": "string", "enum": ["pending", "processing", "completed", "failed", "delivered", "delivery_failed"], "readOnly": true}, "error_message": {"title": "Error message", "type": "string", "readOnly": true, "minLength": 1}, "enrichment_level": {"title": "Enrichment level", "type": "string", "readOnly": true}, "credits_used": {"title": "Credits used", "type": "integer", "readOnly": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}}}, "EnrichmentItem": {"required": ["product_id", "title"], "type": "object", "properties": {"product_id": {"title": "Product id", "description": "The stable, unique identifier for the product in your system (e.g. a SKU, barcode, or database ID). It is the primary way to correlate the webhook response back to your product — it is echoed in every delivery so you know which product was enriched.", "type": "string", "maxLength": 255, "minLength": 1}, "title": {"title": "Title", "description": "Product title.", "type": "string", "maxLength": 1000, "minLength": 1}, "description": {"title": "Description", "description": "Full product description.", "type": "string", "maxLength": 50000}, "url": {"title": "Url", "description": "Canonical URL for the product page.", "type": "string", "format": "uri", "maxLength": 2048}, "category": {"title": "Category", "description": "Product category or breadcrumb path.", "type": "string", "maxLength": 512}, "price": {"title": "Price", "description": "Numeric price (without currency symbol).", "type": "number", "x-nullable": true}, "currency": {"title": "Currency", "description": "ISO 4217 currency code, e.g. `USD`.", "type": "string", "maxLength": 16}, "in_stock": {"title": "In stock", "description": "Whether the product is currently available.", "type": "boolean", "x-nullable": true}, "stock_quantity": {"title": "Stock quantity", "description": "Available inventory units.", "type": "integer", "x-nullable": true}, "tags": {"description": "Existing product tags.", "type": "array", "items": {"type": "string", "maxLength": 255, "minLength": 1}}, "attributes": {"title": "Attributes", "description": "Any additional product attributes (colour, size, material, …). The agent uses these as extra context but does not enrich them directly.", "type": "object", "additionalProperties": {"type": "string", "x-nullable": true}, "default": {}}, "callback_url": {"title": "Callback url", "description": "Override the batch-level `callback_url` for this item only. The same per-key signing secret is used.", "type": "string", "format": "uri", "maxLength": 2048}, "locale": {"title": "Locale", "description": "Override the batch-level `locale` for this item. BCP 47 language tag, e.g. `cs-CZ`.", "type": "string", "maxLength": 16}, "custom_instructions": {"title": "Custom instructions", "description": "Per-item steering for the agent.", "type": "string", "maxLength": 8000}, "enrich_fields": {"description": "Canonical field paths to enrich (e.g. title, description, gtin).", "type": "array", "items": {"type": "string", "minLength": 1}, "maxItems": 64}, "enrichment_level": {"title": "Enrichment level", "description": "How thoroughly to enrich the chosen fields: fast, standard, deep, or auto.", "type": "string", "default": "auto", "minLength": 1}}}, "EnrichmentBatchRequest": {"required": ["products"], "type": "object", "properties": {"callback_url": {"title": "Callback url", "description": "Default callback URL for every item in this batch. Falls back to the API key's configured `webhook_url` when omitted. Per-item `callback_url` overrides this.", "type": "string", "format": "uri", "maxLength": 2048}, "locale": {"title": "Locale", "description": "Default locale (BCP 47) for every item in this batch.", "type": "string", "default": "en-US", "maxLength": 16}, "enrich_fields": {"description": "Default canonical field paths to enrich for every item in this batch.", "type": "array", "items": {"type": "string", "minLength": 1}, "maxItems": 64}, "enrichment_level": {"title": "Enrichment level", "description": "Default enrichment depth for every item in this batch.", "type": "string", "default": "auto", "minLength": 1}, "products": {"description": "Array of products to enrich. 1 to 100 per request. Each item produces one independent agent run and one webhook delivery.", "type": "array", "items": {"$ref": "#/definitions/EnrichmentItem"}, "maxItems": 100, "minItems": 1}}}, "ProductScoreItem": {"required": ["product_id", "title"], "type": "object", "properties": {"product_id": {"title": "Product id", "type": "string", "maxLength": 255, "minLength": 1}, "title": {"title": "Title", "type": "string", "maxLength": 1000, "minLength": 1}, "description": {"title": "Description", "type": "string", "maxLength": 50000}, "url": {"title": "Url", "type": "string", "format": "uri", "maxLength": 2048}, "category": {"title": "Category", "type": "string", "maxLength": 512}, "price": {"title": "Price", "type": "number", "x-nullable": true}, "currency": {"title": "Currency", "type": "string", "maxLength": 16}, "in_stock": {"title": "In stock", "type": "boolean", "x-nullable": true}, "stock_quantity": {"title": "Stock quantity", "type": "integer", "x-nullable": true}, "tags": {"type": "array", "items": {"type": "string", "maxLength": 255, "minLength": 1}}, "attributes": {"title": "Attributes", "type": "object", "additionalProperties": {"type": "string", "x-nullable": true}, "default": {}}}}, "ProductScoreBatchRequest": {"required": ["products"], "type": "object", "properties": {"products": {"type": "array", "items": {"$ref": "#/definitions/ProductScoreItem"}, "maxItems": 100, "minItems": 1}}}, "ProductScoreResult": {"required": ["index", "product_id", "essentials_score", "identifiers_score", "product_detail_score", "overall_health_score", "issues", "issues_count", "agentic_commerce_score", "content_quality_score", "reviews_score"], "type": "object", "properties": {"index": {"title": "Index", "type": "integer"}, "product_id": {"title": "Product id", "type": "string", "minLength": 1}, "essentials_score": {"title": "Essentials score", "description": "0–100 essentials readiness (title, price, image, …).", "type": "integer"}, "identifiers_score": {"title": "Identifiers score", "description": "0–100 identifiers readiness (brand, GTIN/MPN, category).", "type": "integer"}, "product_detail_score": {"title": "Product detail score", "description": "0–100 product detail (extra images, highlights, …).", "type": "integer"}, "overall_health_score": {"title": "Overall health score", "description": "Weighted rollup of the three group scores.", "type": "integer"}, "issues": {"type": "array", "items": {"type": "object", "additionalProperties": {"type": "string", "x-nullable": true}}}, "issues_count": {"title": "Issues count", "type": "integer"}, "agentic_commerce_score": {"title": "Agentic commerce score", "description": "Deprecated alias for essentials_score.", "type": "integer"}, "content_quality_score": {"title": "Content quality score", "description": "Deprecated alias for identifiers_score.", "type": "integer"}, "reviews_score": {"title": "Reviews score", "description": "Deprecated alias for product_detail_score.", "type": "integer"}}}, "ProductScoreBatchResponse": {"required": ["results"], "type": "object", "properties": {"results": {"type": "array", "items": {"$ref": "#/definitions/ProductScoreResult"}}}}, "Provider": {"required": ["id", "code", "name"], "type": "object", "properties": {"id": {"title": "Id", "type": "integer"}, "code": {"title": "Code", "type": "string", "minLength": 1}, "name": {"title": "Name", "type": "string", "minLength": 1}}}, "FanoutQuery": {"required": ["query_text", "frequency", "usage_rate", "prompt_count", "providers", "latest_used_at", "first_seen"], "type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "query_text": {"title": "Query text", "type": "string", "minLength": 1}, "frequency": {"title": "Frequency", "type": "integer"}, "usage_rate": {"title": "Usage rate", "type": "number"}, "usage_rate_variation": {"title": "Usage rate variation", "type": "number", "x-nullable": true}, "prompt_count": {"title": "Prompt count", "type": "integer"}, "providers": {"type": "array", "items": {"$ref": "#/definitions/Provider"}}, "latest_used_at": {"title": "Latest used at", "type": "string", "format": "date-time", "x-nullable": true}, "first_seen": {"title": "First seen", "type": "string", "format": "date-time", "x-nullable": true}}}, "MerchandiserProductList": {"type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "product_name": {"title": "Product name", "type": "string", "readOnly": true, "minLength": 1}, "product_id": {"title": "Product id", "type": "string", "readOnly": true, "minLength": 1}, "sku": {"title": "Sku", "type": "string", "readOnly": true}, "first_image_url": {"title": "First image url", "type": "string", "readOnly": true}, "brand": {"title": "Brand", "type": "string", "readOnly": true}, "brand_favicon_url": {"title": "Brand favicon url", "type": "string", "readOnly": true}, "product_url": {"title": "Product url", "type": "string", "readOnly": true, "minLength": 1}, "in_stock": {"title": "In stock", "type": "boolean", "readOnly": true}, "category": {"title": "Category", "type": "string", "readOnly": true, "minLength": 1}, "price": {"title": "Price", "type": "string", "readOnly": true}, "price_min": {"title": "Price min", "type": "string", "readOnly": true}, "price_max": {"title": "Price max", "type": "string", "readOnly": true}, "currency": {"title": "Currency", "type": "string", "readOnly": true}, "gtin": {"title": "Gtin", "type": "string", "readOnly": true}, "vendors": {"type": "array", "items": {"type": "object"}, "readOnly": true}, "source": {"title": "Source", "type": "string", "readOnly": true}, "feed_source": {"title": "Feed source", "type": "object", "readOnly": true, "x-nullable": true}, "visibility": {"title": "Visibility", "type": "number", "readOnly": true}, "is_visible": {"title": "Is visible", "type": "boolean", "readOnly": true}, "issues_count": {"title": "Issues count", "type": "integer", "readOnly": true}, "issues": {"title": "Issues", "type": "string", "readOnly": true}, "essentials_score": {"title": "Essentials score", "type": "integer", "readOnly": true}, "identifiers_score": {"title": "Identifiers score", "type": "integer", "readOnly": true}, "product_detail_score": {"title": "Product detail score", "type": "integer", "readOnly": true}, "last_enriched_at": {"title": "Last enriched at", "type": "string", "format": "date-time", "x-nullable": true}, "is_enriching": {"title": "Is enriching", "type": "boolean", "readOnly": true}, "is_enriched": {"title": "Is enriched", "type": "boolean", "readOnly": true}, "feed_column_values": {"title": "Feed column values", "type": "object", "readOnly": true}, "variants_count": {"title": "Variants count", "type": "integer", "readOnly": true}}}, "MerchandiserProductDetail": {"type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "product_name": {"title": "Product name", "type": "string", "readOnly": true, "minLength": 1}, "product_id": {"title": "Product id", "type": "string", "readOnly": true, "minLength": 1}, "sku": {"title": "Sku", "type": "string", "readOnly": true}, "first_image_url": {"title": "First image url", "type": "string", "readOnly": true}, "brand": {"title": "Brand", "type": "string", "readOnly": true}, "brand_favicon_url": {"title": "Brand favicon url", "type": "string", "readOnly": true}, "product_url": {"title": "Product url", "type": "string", "readOnly": true, "minLength": 1}, "in_stock": {"title": "In stock", "type": "boolean", "readOnly": true}, "category": {"title": "Category", "type": "string", "readOnly": true, "minLength": 1}, "price": {"title": "Price", "type": "string", "readOnly": true}, "price_min": {"title": "Price min", "type": "string", "readOnly": true}, "price_max": {"title": "Price max", "type": "string", "readOnly": true}, "currency": {"title": "Currency", "type": "string", "readOnly": true}, "gtin": {"title": "Gtin", "type": "string", "readOnly": true}, "vendors": {"type": "array", "items": {"type": "object"}, "readOnly": true}, "source": {"title": "Source", "type": "string", "readOnly": true}, "feed_source": {"title": "Feed source", "type": "object", "readOnly": true, "x-nullable": true}, "visibility": {"title": "Visibility", "type": "number", "readOnly": true}, "is_visible": {"title": "Is visible", "type": "boolean", "readOnly": true}, "issues_count": {"title": "Issues count", "type": "integer", "readOnly": true}, "issues": {"title": "Issues", "type": "string", "readOnly": true}, "essentials_score": {"title": "Essentials score", "type": "integer", "readOnly": true}, "identifiers_score": {"title": "Identifiers score", "type": "integer", "readOnly": true}, "product_detail_score": {"title": "Product detail score", "type": "integer", "readOnly": true}, "last_enriched_at": {"title": "Last enriched at", "type": "string", "format": "date-time", "x-nullable": true}, "is_enriching": {"title": "Is enriching", "type": "boolean", "readOnly": true}, "is_enriched": {"title": "Is enriched", "type": "boolean", "readOnly": true}, "feed_column_values": {"title": "Feed column values", "type": "object", "readOnly": true}, "variants_count": {"title": "Variants count", "type": "integer", "readOnly": true}, "external_id": {"title": "External id", "type": "string", "readOnly": true, "minLength": 1}, "description_html": {"title": "Description html", "type": "string", "readOnly": true, "minLength": 1}, "meta_title": {"title": "Meta title", "type": "string", "readOnly": true, "minLength": 1}, "short_description": {"title": "Short description", "type": "string", "readOnly": true}, "stock_quantity": {"title": "Stock quantity", "type": "string", "readOnly": true, "x-nullable": true}, "tags": {"title": "Tags", "type": "object", "readOnly": true}, "image_urls": {"type": "array", "items": {"type": "string"}, "readOnly": true}, "attributes": {"title": "Attributes", "type": "object", "readOnly": true}, "last_synced_at": {"title": "Last synced at", "type": "string", "format": "date-time", "readOnly": true, "x-nullable": true}, "enriched_params": {"title": "Enriched params", "type": "object", "readOnly": true}, "platform": {"title": "Platform", "type": "string", "readOnly": true, "x-nullable": true}, "variants": {"type": "array", "items": {"type": "object"}, "readOnly": true}, "parameters": {"type": "array", "items": {"type": "object"}, "readOnly": true}}}, "ShareOfVoiceChartData": {"required": ["date", "competitor_name", "visibility_percentage", "is_customer_company"], "type": "object", "properties": {"date": {"title": "Date", "type": "string", "format": "date"}, "competitor_name": {"title": "Competitor name", "type": "string", "minLength": 1}, "visibility_percentage": {"title": "Visibility percentage", "type": "number"}, "is_customer_company": {"title": "Is customer company", "type": "boolean"}, "color": {"title": "Color", "type": "string", "minLength": 1}, "aggregation_period": {"title": "Aggregation period", "type": "string", "minLength": 1}, "competitor_id": {"title": "Competitor id", "type": "string", "minLength": 1, "x-nullable": true}}}, "CustomerChartDataByProvider": {"required": ["date", "provider_name", "provider_code"], "type": "object", "properties": {"date": {"title": "Date", "type": "string", "format": "date"}, "provider_name": {"title": "Provider name", "type": "string", "minLength": 1}, "provider_code": {"title": "Provider code", "type": "string", "minLength": 1}, "visibility_percentage": {"title": "Visibility percentage", "type": "number", "x-nullable": true}, "sentiment_score": {"title": "Sentiment score", "type": "number", "x-nullable": true}, "average_position": {"title": "Average position", "type": "number", "x-nullable": true}, "share_of_voice": {"title": "Share of voice", "type": "number", "x-nullable": true}, "color": {"title": "Color", "type": "string", "minLength": 1}, "aggregation_period": {"title": "Aggregation period", "type": "string", "minLength": 1}}}, "ShareOfVoiceStats": {"required": ["customer_visibility", "top_competitor", "customer_average_position", "customer_average_sentiment"], "type": "object", "properties": {"has_data": {"title": "Has data", "type": "boolean"}, "customer_visibility": {"title": "Customer visibility", "type": "number"}, "customer_share_of_voice": {"title": "Customer share of voice", "type": "number", "x-nullable": true}, "top_competitor": {"title": "Top competitor", "type": "string", "minLength": 1, "x-nullable": true}, "customer_average_position": {"title": "Customer average position", "type": "number", "x-nullable": true}, "customer_average_sentiment": {"title": "Customer average sentiment", "type": "number", "x-nullable": true}, "customer_visibility_variation": {"title": "Customer visibility variation", "type": "number", "x-nullable": true}, "customer_share_of_voice_variation": {"title": "Customer share of voice variation", "type": "number", "x-nullable": true}, "customer_average_position_variation": {"title": "Customer average position variation", "type": "number", "x-nullable": true}, "customer_average_sentiment_variation": {"title": "Customer average sentiment variation", "type": "number", "x-nullable": true}, "total_completions": {"title": "Total completions", "type": "integer", "x-nullable": true}, "search_volume": {"title": "Search volume", "type": "integer", "x-nullable": true}, "search_volume_level": {"title": "Search volume level", "type": "string", "minLength": 1, "x-nullable": true}, "competitors_per_response": {"title": "Competitors per response", "type": "number", "x-nullable": true}, "competitor_difficulty_level": {"title": "Competitor difficulty level", "type": "string", "minLength": 1, "x-nullable": true}, "total_completions_variation": {"title": "Total completions variation", "type": "integer", "x-nullable": true}}}, "PromptList": {"required": ["text", "country"], "type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "text": {"title": "Text", "description": "The actual prompt text to send to LLMs", "type": "string", "minLength": 1}, "company": {"title": "Company", "description": "The company this prompt belongs to", "type": "integer", "x-nullable": true}, "is_active": {"title": "Is active", "description": "Whether to actively complete this prompt", "type": "boolean"}, "is_branded": {"title": "Is branded", "description": "True when prompt text contains the company name or an alias", "type": "boolean", "readOnly": true}, "source": {"title": "Source", "description": "Source for suggested prompts. Manual for actively tracked prompts.", "type": "string", "enum": ["manual", "auto_generated", "recommendation"]}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}, "country": {"title": "Country", "description": "Target country for this prompt.", "type": "integer"}, "region": {"title": "Region", "description": "Target region for this prompt. If empty, uses company's region.", "type": "string", "maxLength": 255, "x-nullable": true}, "city": {"title": "City", "description": "Target city for this prompt. If empty, uses company's city.", "type": "string", "maxLength": 255, "x-nullable": true}, "persona": {"title": "Persona", "description": "Optional persona to personalize responses for this prompt. If not set, responses will not be personalized.", "type": "integer", "x-nullable": true}, "topic": {"title": "Topic", "description": "Optional topic to organize this prompt. If not set, prompt will be uncategorized.", "type": "integer", "x-nullable": true}, "intent": {"title": "Intent", "description": "Primary search intent, auto-detected when prompt is created.", "type": "string", "enum": ["informational", "navigational", "transactional", "commercial"], "x-nullable": true}, "is_loading": {"title": "Is loading", "type": "boolean", "readOnly": true}}}, "Prompt": {"required": ["text", "country"], "type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "text": {"title": "Text", "description": "The actual prompt text to send to LLMs", "type": "string", "minLength": 1}, "company": {"title": "Company", "description": "The company this prompt belongs to", "type": "integer", "x-nullable": true}, "created_by": {"title": "Created by", "type": "string", "readOnly": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}, "is_active": {"title": "Is active", "description": "Whether to actively complete this prompt", "type": "boolean"}, "is_branded": {"title": "Is branded", "description": "True when prompt text contains the company name or an alias", "type": "boolean", "readOnly": true}, "source": {"title": "Source", "description": "Source for suggested prompts. Manual for actively tracked prompts.", "type": "string", "enum": ["manual", "auto_generated", "recommendation"], "readOnly": true}, "country": {"title": "Country", "description": "Target country for this prompt.", "type": "integer"}, "region": {"title": "Region", "description": "Target region for this prompt. If empty, uses company's region.", "type": "string", "maxLength": 255, "x-nullable": true}, "city": {"title": "City", "description": "Target city for this prompt. If empty, uses company's city.", "type": "string", "maxLength": 255, "x-nullable": true}, "persona": {"title": "Persona", "description": "Optional persona to personalize responses for this prompt. If not set, responses will not be personalized.", "type": "integer", "x-nullable": true}, "topic": {"title": "Topic", "description": "Optional topic to organize this prompt. If not set, prompt will be uncategorized.", "type": "integer", "x-nullable": true}, "intent": {"title": "Intent", "description": "Primary search intent, auto-detected when prompt is created.", "type": "string", "enum": ["informational", "navigational", "transactional", "commercial"], "x-nullable": true}, "completion_frequency": {"title": "Completion frequency", "description": "How often to complete LLMs for this prompt", "type": "string", "enum": ["daily", "weekly", "monthly"]}, "tag_ids": {"type": "array", "items": {"type": "string", "minLength": 1}}}}, "CompletionOverall": {"type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "response_text": {"title": "Response text", "type": "string", "readOnly": true}, "queried_at": {"title": "Queried at", "description": "When this completion should be processed. Used for both scheduling and charts.", "type": "string", "format": "date-time", "readOnly": true}, "llm_provider_name": {"title": "Llm provider name", "type": "string", "readOnly": true, "minLength": 1}, "llm_provider_code": {"title": "Llm provider code", "type": "string", "readOnly": true, "minLength": 1}, "processing_status": {"title": "Processing status", "type": "string", "enum": ["pending", "processing", "completed", "error"]}, "competitor_mentions": {"title": "Competitor mentions", "type": "string", "readOnly": true}, "mentioned": {"title": "Mentioned", "type": "string", "readOnly": true}, "cited": {"title": "Cited", "type": "string", "readOnly": true}, "started_processing_at": {"title": "Started processing at", "type": "string", "format": "date-time", "readOnly": true}, "completed_at": {"title": "Completed at", "type": "string", "format": "date-time", "readOnly": true}, "processing_duration_seconds": {"title": "Processing duration seconds", "type": "number", "readOnly": true}, "total_duration_seconds": {"title": "Total duration seconds", "type": "number", "readOnly": true}, "prompt_id": {"title": "Prompt id", "type": "string", "readOnly": true}, "prompt_text": {"title": "Prompt text", "type": "string", "readOnly": true, "minLength": 1}, "citations_count": {"title": "Citations count", "type": "integer", "readOnly": true}, "sentiment_score": {"title": "Sentiment score", "type": "string", "readOnly": true}, "sentiment_label": {"title": "Sentiment label", "type": "string", "readOnly": true}}}, "TrackedCompanyMetric": {"required": ["name", "visibility", "share_of_voice", "average_position", "average_sentiment", "is_customer_company"], "type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "name": {"title": "Name", "type": "string", "minLength": 1}, "visibility": {"title": "Visibility", "type": "number"}, "share_of_voice": {"title": "Share of voice", "type": "number"}, "average_position": {"title": "Average position", "type": "number", "x-nullable": true}, "average_sentiment": {"title": "Average sentiment", "type": "number", "x-nullable": true}, "is_customer_company": {"title": "Is customer company", "type": "boolean"}, "rank": {"title": "Rank", "type": "integer", "x-nullable": true}, "color": {"title": "Color", "type": "string", "minLength": 1}, "favicon_url": {"title": "Favicon url", "type": "string", "format": "uri", "minLength": 1, "x-nullable": true}, "quality_score": {"title": "Quality score", "type": "number", "x-nullable": true}, "visibility_variation": {"title": "Visibility variation", "type": "number", "x-nullable": true}, "share_of_voice_variation": {"title": "Share of voice variation", "type": "number", "x-nullable": true}, "average_position_variation": {"title": "Average position variation", "type": "number", "x-nullable": true}, "average_sentiment_variation": {"title": "Average sentiment variation", "type": "number", "x-nullable": true}}}, "CompletionWithMentions": {"type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "response_text": {"title": "Response text", "type": "string", "readOnly": true}, "queried_at": {"title": "Queried at", "description": "When this completion should be processed. Used for both scheduling and charts.", "type": "string", "format": "date-time", "readOnly": true}, "llm_provider_name": {"title": "Llm provider name", "type": "string", "readOnly": true, "minLength": 1}, "llm_provider_code": {"title": "Llm provider code", "type": "string", "readOnly": true, "minLength": 1}, "processing_status": {"title": "Processing status", "type": "string", "enum": ["pending", "processing", "completed", "error"]}, "competitor_mentions": {"title": "Competitor mentions", "type": "string", "readOnly": true}, "mentioned": {"title": "Mentioned", "type": "string", "readOnly": true}, "cited": {"title": "Cited", "type": "string", "readOnly": true}, "started_processing_at": {"title": "Started processing at", "type": "string", "format": "date-time", "readOnly": true}, "completed_at": {"title": "Completed at", "type": "string", "format": "date-time", "readOnly": true}, "processing_duration_seconds": {"title": "Processing duration seconds", "type": "number", "readOnly": true}, "total_duration_seconds": {"title": "Total duration seconds", "type": "number", "readOnly": true}}}, "SearchQueryFrequency": {"required": ["query_text", "frequency", "usage_rate", "query_share", "prompt_count", "providers", "latest_used_at", "first_seen"], "type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "query_text": {"title": "Query text", "type": "string", "minLength": 1}, "frequency": {"title": "Frequency", "type": "integer"}, "usage_rate": {"title": "Usage rate", "type": "number"}, "usage_rate_variation": {"title": "Usage rate variation", "type": "number", "x-nullable": true}, "query_share": {"title": "Query share", "type": "number"}, "prompt_count": {"title": "Prompt count", "type": "integer"}, "providers": {"type": "array", "items": {"type": "object", "additionalProperties": {"type": "string", "minLength": 1}}}, "latest_used_at": {"title": "Latest used at", "type": "string", "format": "date-time", "x-nullable": true}, "first_seen": {"title": "First seen", "type": "string", "format": "date-time", "x-nullable": true}}}, "SiteAuditList": {"required": ["base_url"], "type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "crawl_source": {"title": "Crawl source", "type": "string", "enum": ["sitemap", "automatic", "manual"]}, "base_url": {"title": "Base url", "description": "Base URL where crawl started (e.g. https://example.com)", "type": "string", "format": "uri", "maxLength": 2048, "minLength": 1}, "status": {"title": "Status", "type": "string", "enum": ["pending", "crawling", "analyzing", "completed", "failed", "cancelled"]}, "error_message": {"title": "Error message", "type": "string", "x-nullable": true}, "pages_count": {"title": "Pages count", "type": "integer", "maximum": 2147483647, "minimum": 0}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}}}, "SiteAuditIssue": {"required": ["text", "severity"], "type": "object", "properties": {"text": {"title": "Text", "type": "string", "maxLength": 512, "minLength": 1}, "severity": {"title": "Severity", "type": "string", "enum": ["minor", "moderate", "critical"]}, "category": {"title": "Category", "description": "Which scorer produced this issue", "type": "string", "enum": ["technical_seo", "content_quality", "aeo"]}, "highlight_target": {"title": "Highlight target", "type": "string", "readOnly": true}}}, "SiteAuditPage": {"required": ["url"], "type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "url": {"title": "Url", "type": "string", "format": "uri", "maxLength": 2048, "minLength": 1}, "meta_title": {"title": "Meta title", "type": "string", "maxLength": 512}, "meta_description": {"title": "Meta description", "type": "string"}, "overall_score": {"title": "Overall score", "description": "0-100 overall score", "type": "integer", "maximum": 32767, "minimum": 0}, "img_alt_tags_score": {"title": "Img alt tags score", "description": "0-100, share of images with valid alt tags", "type": "integer", "maximum": 32767, "minimum": 0}, "technical_seo_score": {"title": "Technical seo score", "description": "0-100 from custom prompt", "type": "integer", "maximum": 32767, "minimum": 0}, "content_quality_score": {"title": "Content quality score", "description": "0-100 from custom prompt", "type": "integer", "maximum": 32767, "minimum": 0}, "aeo_score": {"title": "Aeo score", "description": "0-100 AI/Answer Engine Optimization from custom prompt", "type": "integer", "maximum": 32767, "minimum": 0}, "page_type": {"title": "Page type", "description": "Heuristic page type used for type-aware scoring", "type": "string", "maxLength": 32}, "screenshot_url": {"title": "Screenshot url", "description": "Cloudinary URL of the latest Playwright page screenshot", "type": "string", "format": "uri", "maxLength": 2048}, "issues": {"type": "array", "items": {"$ref": "#/definitions/SiteAuditIssue"}, "readOnly": true}, "uplift": {"title": "Uplift", "type": "string", "readOnly": true}, "history": {"title": "History", "type": "string", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}}}, "SiteAudit": {"required": ["base_url"], "type": "object", "properties": {"id": {"title": "Id", "type": "string", "readOnly": true}, "crawl_source": {"title": "Crawl source", "type": "string", "enum": ["sitemap", "automatic", "manual"]}, "sitemap_url": {"title": "Sitemap url", "description": "URL of sitemap.xml when crawl_source is sitemap", "type": "string", "format": "uri", "maxLength": 2048, "x-nullable": true}, "base_url": {"title": "Base url", "description": "Base URL where crawl started (e.g. https://example.com)", "type": "string", "format": "uri", "maxLength": 2048, "minLength": 1}, "status": {"title": "Status", "type": "string", "enum": ["pending", "crawling", "analyzing", "completed", "failed", "cancelled"]}, "error_message": {"title": "Error message", "type": "string", "x-nullable": true}, "pages_count": {"title": "Pages count", "type": "integer", "maximum": 2147483647, "minimum": 0}, "pages": {"type": "array", "items": {"$ref": "#/definitions/SiteAuditPage"}, "readOnly": true}, "created_at": {"title": "Created at", "type": "string", "format": "date-time", "readOnly": true}, "updated_at": {"title": "Updated at", "type": "string", "format": "date-time", "readOnly": true}}}}, "tags": [{"name": "Reference", "description": "Lookup endpoints for AI providers, countries, and languages. Call these first to discover the IDs you need as filter values in other endpoints."}, {"name": "Overview"}, {"name": "Sentiment", "description": "Customer brand sentiment from mention snippets: score over time, positive/negative highlights, head-to-head perception vs a competitor, and citation source domains for filtering."}, {"name": "Prompts"}, {"name": "Citations"}, {"name": "Query Fanouts"}, {"name": "Site Audit"}, {"name": "Content"}, {"name": "Shopping"}, {"name": "Enrichment", "description": "Programmatic product enrichment for PIMs and custom integrations. Send\nyour products with their canonical fields and Ranketta returns them\nenriched with AI-generated titles, descriptions, taxonomy, GTIN\ncandidates, FAQ entries and more.\n\nThe API is **stateless and async**: each call queues one or more\nbackground runs and delivers results to your webhook when they complete.\n\n## Product structure\n\nEach item uses a flat, well-defined structure. The two required fields\nare `product_id` and `title`. Everything else is optional but improves\nenrichment quality:\n\n| Field            | Type    | Required |\n|------------------|---------|----------|\n| `product_id`     | string  | ✓        |\n| `title`          | string  | ✓        |\n| `description`    | string  |          |\n| `url`            | string  |          |\n| `category`       | string  |          |\n| `price`          | number  |          |\n| `currency`       | string  |          |\n| `in_stock`       | boolean |          |\n| `stock_quantity` | integer |          |\n| `tags`           | array   |          |\n| `attributes`     | object  |          |\n\nUse `attributes` for any extra fields your PIM carries (colour, size,\nmaterial, …). The agent uses them as context but does not enrich them\ndirectly.\n\n## Enrichment level\n\nPass `enrich_fields` at batch or item level to choose which fields to enrich.\nPass `enrichment_level` to control how thoroughly those fields are enriched:\n\n| Level      | Typical credits | Depth |\n|------------|-----------------|-------|\n| `fast`     | ~100            | Quick pass from existing product data |\n| `standard` | ~500            | Balanced quality with moderate research |\n| `deep`     | ~1,000          | Maximum research and polish |\n| `auto`     | varies          | Agent adapts effort per field (default) |\n\nActual credits charged are computed from real API costs with an 80% gross\nmargin (returned as `credits_used` in the webhook). Credits do not roll\nover between billing periods.\n\n## Credits and quota\n\nEnrichment consumes credits from your organization's monthly allowance.\nIf remaining credits are insufficient for the estimated level cost,\nitems are rejected with `credits_insufficient`.\n\n## Product score\n\n`POST /v1/enrichments/score` scores product data quality **synchronously**\n(no credits, no webhook). Each item uses the same deterministic logic as the\nmerchandiser dashboard — three readiness groups: **Essentials**,\n**Identifiers**, and **Product detail**.\n\nRequest body: `products[]` (1–100 items). Required per item: `product_id`,\n`title`. Optional: `description`, `url`, `category`, `price`, `currency`,\n`in_stock`, `stock_quantity`, `tags`, `attributes`.\n\nResponse per item:\n\n| Field | Description |\n|-------|-------------|\n| `essentials_score` | 0–100 essentials readiness (title, description, link, image, price, availability) |\n| `identifiers_score` | 0–100 identifiers readiness (brand, GTIN/MPN, category) |\n| `product_detail_score` | 0–100 product detail (extra images, highlights, apparel/variant attributes) |\n| `overall_health_score` | Weighted rollup of the three group scores |\n| `issues` | Actionable gaps (`field_path`, `severity`, `text`) |\n| `issues_count` | Number of issues returned |\n\n**Deprecated aliases** (same values, kept so existing clients keep working):\n\n| Alias | Canonical field |\n|-------|-----------------|\n| `agentic_commerce_score` | `essentials_score` |\n| `content_quality_score` | `identifiers_score` |\n| `reviews_score` | `product_detail_score` |\n\n## Batching\n\n`POST /v1/enrichments` accepts a `products[]` array (1–100 items).\nEach item produces one independent agent run and one webhook delivery.\n\n* **Automatic deduplication** — identical submissions are detected via\n  a content hash; repeating the same product returns the original\n  `request_id` without starting a new run.\n* **Partial acceptance** — items missing required fields are reported\n  in `rejected[]`; the rest still get queued.\n* **Mid-batch quota** — items beyond your remaining credit balance are\n  reported with `credits_insufficient`; the rest still run.\n\n## Webhook payload\n\nWhen enrichment completes, Ranketta POSTs the following JSON to your\ncallback URL.\n\n**Success**\n\n```json\n{\n  \"request_id\": \"8b7e2d4f-3c4f-4e58-b6c2-a1d6f0c9e1a2\",\n  \"product_id\": \"SKU-1042\",\n  \"created_at\": \"2026-05-03T20:00:00Z\",\n  \"run_id\": 18321,\n  \"status\": \"completed\",\n  \"enrichment_level\": \"auto\",\n  \"credits_used\": 127,\n  \"product\": {\n    \"product_id\": \"SKU-1042\",\n    \"title\": \"Premium Organic Cotton T-Shirt\",\n    \"description\": \"Soft, sustainably sourced organic cotton. Pre-washed …\",\n    \"category\": \"Apparel > Tops > T-Shirts\",\n    \"tags\": [\"organic\", \"cotton\", \"sustainable\", \"unisex\"],\n    \"attributes\": { \"vendor\": \"EcoWear\" }\n  },\n  \"enriched_fields\": {\n    \"title\": {\n      \"old_value\": \"Cotton T-Shirt\",\n      \"new_value\": \"Premium Organic Cotton T-Shirt\",\n      \"confidence\": 0.96,\n      \"rationale\": \"Added 'Premium Organic' based on material attributes.\"\n    },\n    \"description\": {\n      \"old_value\": \"\",\n      \"new_value\": \"Soft, sustainably sourced organic cotton. Pre-washed …\",\n      \"confidence\": 0.91,\n      \"rationale\": \"Generated from title, vendor, and material keywords.\"\n    }\n  },\n  \"overall_confidence\": 0.93,\n  \"skipped\": [],\n  \"completed_at\": \"2026-05-03T20:00:28Z\"\n}\n```\n\n`product` is your original payload with enriched values applied in\nplace. `enriched_fields` provides a diff view with confidence scores\nand rationale for each enriched attribute.\n\n**Failure**\n\n```json\n{\n  \"request_id\": \"8b7e2d4f-3c4f-4e58-b6c2-a1d6f0c9e1a2\",\n  \"product_id\": \"SKU-1042\",\n  \"created_at\": \"2026-05-03T20:00:00Z\",\n  \"run_id\": null,\n  \"status\": \"failed\",\n  \"error\": \"enrichment_failed\"\n}\n```\n\n## Webhook signing\n\nEach delivery is signed with HMAC-SHA256:\n\n```\nX-Ranketta-Signature: t=<unix>,v1=<hex>\nX-Ranketta-Request-Id: <uuid>\n```\n\nThe signed payload is `\"{t}.{raw_body}\"`. Reject payloads whose\ntimestamp drifts more than five minutes from your server clock.\n"}]}