{
  "openapi": "3.1.0",
  "info": {
    "title": "SpeedyIndex API",
    "version": "2.0",
    "summary": "Link indexing, index checking, backlink checking and Google rank tracking.",
    "description": "SpeedyIndex API v2 lets you submit URLs for indexing in Google and Yandex, check whether URLs are indexed\nin Google, Yandex and Bing, check donor pages for backlinks, and track Google rankings and AI Overview\ncitations with the Rank Tracker.\n\n**Authentication.** Send your API key in the `Authorization` header as it is, without `Bearer`.\nCopy the key from the API section of your SpeedyIndex dashboard. POST, PUT and PATCH requests send JSON\nwith `Content-Type: application/json`.\n\n**Responses.** Every response has a numeric `code`: `0` means success. Indexing endpoints use\n`1` insufficient balance or not found, `2` validation error, `3` rate limit or server error.\nRank Tracker errors also have `error` (a stable machine-readable name) and `message`.\n\n**Rate limits.** Indexing, checking and backlink endpoints: 120 requests per minute per IP address.\nRank Tracker: per API key, 600 reads (GET) and 120 writes a minute, at most 8 requests at once.\nOver a limit you get HTTP 429 with `Retry-After`.\n\n**Prices.** Google indexing runs in Pay per Indexed mode: 100 tokens per URL, 100% refund for URLs not\nindexed after 7 days. Yandex indexing: 20 tokens per URL, Pay per Indexed always on, refund after 15 days.\nA Rank Tracker check costs tokens per loaded results page; read current prices from `GET /v2/rank-tracker/limits`.\n\nSource: the official SpeedyIndex API documentation, https://app.speedyindex.com/Documentation.pdf\n",
    "contact": {
      "name": "SpeedyIndex support",
      "email": "support@speedyindex.com",
      "url": "https://en.speedyindex.com/"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://en.speedyindex.com/"
    },
    "termsOfService": "https://en.speedyindex.com/privacy-policy/",
    "x-logo": {
      "url": "https://en.speedyindex.com/favicon.ico"
    }
  },
  "externalDocs": {
    "description": "Official API documentation (PDF)",
    "url": "https://app.speedyindex.com/Documentation.pdf"
  },
  "servers": [
    {
      "url": "https://api.speedyindex.com",
      "description": "Production"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "Balance and top-up invoices."
    },
    {
      "name": "Indexing and index checks",
      "description": "Tasks that submit URLs for indexing (Google, Yandex) or check index status (Google, Yandex, Bing)."
    },
    {
      "name": "Single URL indexing",
      "description": "Submit one URL without creating a task manually."
    },
    {
      "name": "Backlink checker",
      "description": "Open donor pages and find links to your target domains."
    },
    {
      "name": "Rank Tracker - reference",
      "description": "Limits, prices, locations, groups and spending."
    },
    {
      "name": "Rank Tracker - projects",
      "description": "Sites tracked in Google with their regions, keywords, competitors and schedule."
    },
    {
      "name": "Rank Tracker - regions",
      "description": "Every keyword is checked in every region of its project. A removed region keeps its history."
    },
    {
      "name": "Rank Tracker - keywords and tags",
      "description": "Keywords are matched by text ignoring case and spaces. Tags are lowercase, up to 40 characters, at most 10 per keyword."
    },
    {
      "name": "Rank Tracker - checks",
      "description": "A check holds cost.max tokens when it starts and gives back what it did not spend when it ends. One check runs per project at a time."
    },
    {
      "name": "Rank Tracker - results",
      "description": "Positions, trends, keyword details with AI Overview data, and exports. Positions are kept for 365 days."
    },
    {
      "name": "Rank Tracker - webhooks",
      "description": "One webhook URL per account gets the events of all projects; a project's own webhook_url gets that project's events instead."
    }
  ],
  "paths": {
    "/v2/account": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getBalance",
        "summary": "Check the balance",
        "description": "Returns your current balance across all services.",
        "responses": {
          "200": {
            "description": "Balance",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "balance": {
                      "type": "object",
                      "properties": {
                        "tokens": {
                          "type": "integer",
                          "description": "Token balance"
                        },
                        "indexer": {
                          "type": "integer",
                          "description": "Indexing credits"
                        },
                        "checker": {
                          "type": "integer",
                          "description": "Index check credits"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "balance": {
                    "tokens": 5000,
                    "indexer": 10014495,
                    "checker": 100732
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v2/account/invoice/create": {
      "post": {
        "tags": [
          "Account"
        ],
        "operationId": "createInvoice",
        "summary": "Create an invoice to purchase tokens",
        "description": "Available packages: $5 (5,000), $20 (30,000), $50 (120,000), $100 (250,000), $250 (700,000), $500 (1,500,000 tokens).\nPayPal: +10% fee. YooKassa: USD to RUB (1 USD = 100 RUB), requires email.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "price",
                  "method"
                ],
                "properties": {
                  "price": {
                    "type": "number",
                    "enum": [
                      5,
                      20,
                      50,
                      100,
                      250,
                      500
                    ],
                    "description": "Package price in USD"
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "crypto",
                      "paypal",
                      "yookassa"
                    ],
                    "description": "Payment method"
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "description": "Required for yookassa. Email for the payment receipt."
                  }
                }
              },
              "example": {
                "price": 50,
                "method": "crypto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "result": {
                      "type": "string",
                      "format": "uri",
                      "description": "Payment invoice URL"
                    },
                    "tokens_amount": {
                      "type": "integer",
                      "description": "Tokens to be credited"
                    },
                    "price": {
                      "type": "number",
                      "description": "Final price (USD or RUB)"
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "USD",
                        "RUB"
                      ]
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "result": "https://pay.cryptocloud.plus/LJQ18AI1?lang=en",
                  "tokens_amount": 120000,
                  "price": 50,
                  "currency": "USD"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v2/task/{search_engine}/{task_type}/create": {
      "post": {
        "tags": [
          "Indexing and index checks"
        ],
        "operationId": "createTask",
        "summary": "Create an indexing or index check task",
        "description": "`search_engine`: google, yandex, bing. `task_type`: indexer, checker. Bing supports checker only.\n\nCurrently only the `pay_per_indexed: true` mode is available for Google indexing tasks; standard Google indexing is temporarily unavailable.\nGoogle indexer: 100 tokens/URL, 100% refund for unindexed links after 7 days.\nYandex indexer: Pay per Indexed is always on, 20 tokens/URL, 100% refund for unindexed links after 15 days.\nIndexing credits are spent first (1 credit/URL); tokens are charged only for the URLs left uncovered.\n\nDrip Feed (google/indexer only): set `drip_feed: true` and `drip_feed_days` (2-30) to spread submissions\nacross several days in equal daily batches. The number of URLs must be at least `drip_feed_days`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SearchEngine"
          },
          {
            "$ref": "#/components/parameters/TaskType"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "urls"
                ],
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Task name"
                  },
                  "urls": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    },
                    "maxItems": 10000
                  },
                  "pay_per_indexed": {
                    "type": "boolean",
                    "description": "true for Pay per Indexed (google/indexer). Not needed for yandex/indexer."
                  },
                  "drip_feed": {
                    "type": "boolean",
                    "description": "true to create a Drip Feed task (google/indexer only)"
                  },
                  "drip_feed_days": {
                    "type": "integer",
                    "minimum": 2,
                    "maximum": 30,
                    "description": "Required if drip_feed is true"
                  }
                }
              },
              "example": {
                "title": "my task",
                "urls": [
                  "https://example.com/page1",
                  "https://example.com/page2"
                ],
                "pay_per_indexed": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task created (code 0), or refused: code 1 insufficient balance, code 2 validation error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "task_id": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "example": "google/indexer"
                    },
                    "pay_per_indexed": {
                      "type": "boolean"
                    },
                    "drip_feed": {
                      "type": "boolean"
                    },
                    "drip_feed_days": {
                      "type": "integer"
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "task_id": "6609d023a3188540f09fec6c",
                  "type": "google/indexer",
                  "pay_per_indexed": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          },
          "413": {
            "$ref": "#/components/responses/PayloadTooLarge"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v2/task/{search_engine}/{task_type}/list/{page}": {
      "get": {
        "tags": [
          "Indexing and index checks"
        ],
        "operationId": "listTasks",
        "summary": "List tasks",
        "description": "Up to 1000 tasks per page, newest first. Pages start at 0.\n`filter` (google/indexer only): standard, pay_per_indexed or drip_feed. Without a filter: standard and Pay per Indexed tasks (no Drip Feed).\nCombine `filter=drip_feed` with `pay_per_indexed=true|false` to filter Drip Feed tasks by type.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SearchEngine"
          },
          {
            "$ref": "#/components/parameters/TaskType"
          },
          {
            "name": "page",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "name": "filter",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "standard",
                "pay_per_indexed",
                "drip_feed"
              ]
            }
          },
          {
            "name": "pay_per_indexed",
            "in": "query",
            "description": "With filter=drip_feed only.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of tasks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "last_page": {
                      "type": "integer"
                    },
                    "result": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Task"
                      }
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "page": 0,
                  "last_page": 0,
                  "result": [
                    {
                      "id": "65f8c7315752853b9171860a",
                      "size": 690,
                      "processed_count": 690,
                      "indexed_count": 279,
                      "title": "my_urls.txt",
                      "is_completed": true,
                      "type": "google/indexer",
                      "created_at": "2024-03-18T22:58:56.901Z"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v2/task/{search_engine}/{task_type}/status": {
      "post": {
        "tags": [
          "Indexing and index checks"
        ],
        "operationId": "getTaskStatus",
        "summary": "Get the status of tasks",
        "description": "Provide either `task_id` or `task_ids`. Pay per Indexed tasks add status, tokens_charged, tokens_refunded and check_after.\nFor a single Drip Feed task the response adds days, days_passed, is_stopped, child_task_ids and a `children` array.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SearchEngine"
          },
          {
            "$ref": "#/components/parameters/TaskType"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskIdOrIds"
              },
              "example": {
                "task_id": "65f8c7305759855b9171860a"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task or tasks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "result": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Task"
                        },
                        {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Task"
                          }
                        }
                      ]
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "result": {
                    "id": "65f8c7305759855b9171860a",
                    "size": 690,
                    "processed_count": 690,
                    "indexed_count": 279,
                    "is_completed": true,
                    "title": "my_urls.txt",
                    "type": "google/indexer",
                    "created_at": "2024-03-18T22:58:56.901Z",
                    "pay_per_indexed": true,
                    "status": "completed",
                    "tokens_charged": 69000,
                    "tokens_refunded": 41100,
                    "check_after": "2024-03-25T22:58:56.901Z"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v2/task/{search_engine}/{task_type}/report": {
      "post": {
        "tags": [
          "Indexing and index checks"
        ],
        "operationId": "getTaskReport",
        "summary": "Download a task report",
        "description": "Indexed and unindexed URL lists. For a Drip Feed task the lists are aggregated across all child tasks.",
        "parameters": [
          {
            "$ref": "#/components/parameters/SearchEngine"
          },
          {
            "$ref": "#/components/parameters/TaskType"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskIdBody"
              },
              "example": {
                "task_id": "653278d8a2b987d72b36f2a2"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Report",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "result": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/ReportBase"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "indexed_links": {
                              "type": "array",
                              "items": {
                                "type": "string",
                                "format": "uri"
                              }
                            },
                            "unindexed_links": {
                              "type": "array",
                              "items": {
                                "type": "string",
                                "format": "uri"
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "result": {
                    "id": "653278d8a2b987d72b36f2a2",
                    "size": 3,
                    "processed_count": 3,
                    "indexed_links": [
                      "https://example.com/page1"
                    ],
                    "unindexed_links": [
                      "https://example.com/page2"
                    ],
                    "title": "test",
                    "type": "google/indexer",
                    "created_at": "2023-10-20T12:55:52.031Z",
                    "pay_per_indexed": true,
                    "tokens_charged": 300,
                    "tokens_refunded": 100
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v2/task/{search_engine}/{task_type}/fullreport": {
      "post": {
        "tags": [
          "Indexing and index checks"
        ],
        "operationId": "getTaskFullReport",
        "summary": "Download a full task report with page titles",
        "description": "Same as the report, but each indexed link is `{url, title}`, where title is the page title in the search results\nof the selected engine (empty string if unavailable). Unindexed links are `{url, error_code}` for standard tasks\nand `{url}` for Pay per Indexed and Drip Feed tasks.\nerror_code: -1 meta noindex found, 0 no errors, other values are the HTTP status found on the page.\nyandex/indexer: links are marked indexed only after the automatic final check 15 days after the task is created.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SearchEngine"
          },
          {
            "$ref": "#/components/parameters/TaskType"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskIdBody"
              },
              "example": {
                "task_id": "653278d8a2b987d72b36f2a2"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Full report",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "result": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/ReportBase"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "indexed_links": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "url": {
                                    "type": "string",
                                    "format": "uri"
                                  },
                                  "title": {
                                    "type": "string"
                                  }
                                }
                              }
                            },
                            "unindexed_links": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "url": {
                                    "type": "string",
                                    "format": "uri"
                                  },
                                  "error_code": {
                                    "type": "integer"
                                  }
                                }
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "result": {
                    "id": "653278d8a2b987d72b36f2a2",
                    "size": 3,
                    "processed_count": 3,
                    "indexed_links": [
                      {
                        "url": "https://example.com/page1",
                        "title": "Page Title"
                      }
                    ],
                    "unindexed_links": [
                      {
                        "url": "https://example.com/page2"
                      }
                    ],
                    "title": "test",
                    "type": "google/indexer",
                    "created_at": "2023-10-20T12:55:52.031Z",
                    "pay_per_indexed": true,
                    "tokens_charged": 300,
                    "tokens_refunded": 100
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v2/task/backlink/checker/create": {
      "post": {
        "tags": [
          "Backlink checker"
        ],
        "operationId": "createBacklinkCheck",
        "summary": "Create a backlink check task",
        "description": "Check donor pages for backlinks to your target domains. Up to 10,000 donor URLs and 50 target domains per task.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "urls",
                  "target_domains"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "urls": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    },
                    "maxItems": 10000,
                    "description": "Donor URLs to check"
                  },
                  "target_domains": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "maxItems": 50,
                    "example": [
                      "mydomain.com"
                    ]
                  }
                }
              },
              "example": {
                "title": "backlink check",
                "urls": [
                  "https://donor1.com/page",
                  "https://donor2.com/page"
                ],
                "target_domains": [
                  "mydomain.com"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task created (code 0), or refused: code 1 insufficient balance, code 2 validation error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "task_id": {
                      "type": "string"
                    },
                    "type": {
                      "type": "string",
                      "const": "backlink/checker"
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "task_id": "680abc123def456",
                  "type": "backlink/checker"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/InsufficientBalance"
          }
        }
      }
    },
    "/v2/task/backlink/checker/status": {
      "post": {
        "tags": [
          "Backlink checker"
        ],
        "operationId": "getBacklinkCheckStatus",
        "summary": "Get the status of backlink check tasks",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskIdOrIds"
              },
              "example": {
                "task_id": "680abc123def456"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Task or tasks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "result": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/BacklinkTask"
                        },
                        {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/BacklinkTask"
                          }
                        }
                      ]
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "result": {
                    "id": "680abc123def456",
                    "size": 100,
                    "processed_count": 100,
                    "title": "backlink check",
                    "target_domains": [
                      "mydomain.com"
                    ],
                    "is_completed": true,
                    "type": "backlink/checker",
                    "created_at": "2024-10-20T12:55:52.031Z"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v2/task/backlink/checker/report": {
      "post": {
        "tags": [
          "Backlink checker"
        ],
        "operationId": "getBacklinkCheckReport",
        "summary": "Download a backlink check report",
        "description": "For each donor URL — HTTP status, Moz Domain Authority, Moz spam score, indexability and the links found to the target domains. Paged, up to 100 donors per page.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "task_id"
                ],
                "properties": {
                  "task_id": {
                    "type": "string"
                  },
                  "page": {
                    "type": "integer",
                    "minimum": 0,
                    "default": 0
                  },
                  "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100
                  }
                }
              },
              "example": {
                "task_id": "680abc123def456",
                "page": 0,
                "limit": 50
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A page of the report",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "result": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "size": {
                          "type": "integer"
                        },
                        "processed_count": {
                          "type": "integer"
                        },
                        "is_completed": {
                          "type": "boolean"
                        },
                        "page": {
                          "type": "integer"
                        },
                        "last_page": {
                          "type": "integer"
                        },
                        "donors": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Donor"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "result": {
                    "id": "680abc123def456",
                    "size": 2,
                    "processed_count": 2,
                    "is_completed": true,
                    "page": 0,
                    "last_page": 0,
                    "donors": [
                      {
                        "donor_url": "https://donor1.com/page",
                        "processed": true,
                        "http_status": 200,
                        "moz_domain_authority": 45,
                        "moz_spam_score": 3,
                        "target_links": [
                          {
                            "url": "https://mydomain.com/article",
                            "anchor": "read more",
                            "nofollow": false
                          }
                        ]
                      }
                    ]
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v2/{search_engine}/url": {
      "post": {
        "tags": [
          "Single URL indexing"
        ],
        "operationId": "submitSingleUrl",
        "summary": "Index a single link",
        "description": "`search_engine`: google or yandex.\nGoogle: pass `pay_per_indexed: true` for 100 tokens/URL with a 100% refund for unindexed links after 7 days; without it, standard indexing credits are used (1 credit/URL).\nYandex: Pay per Indexed is always on (refund after 15 days). Indexing credits are spent first; when they run out, 20 tokens/URL are charged. The flag is accepted but has no effect.\n",
        "parameters": [
          {
            "name": "search_engine",
            "in": "path",
            "required": true,
            "example": "google",
            "schema": {
              "type": "string",
              "enum": [
                "google",
                "yandex"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "pay_per_indexed": {
                    "type": "boolean"
                  }
                }
              },
              "example": {
                "url": "https://example.com/page",
                "pay_per_indexed": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "code 0 success, 1 insufficient balance, 2 invalid URL, 3 daily limit exceeded or the task could not be created (the charge is refunded)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "task_id": {
                      "type": "string",
                      "description": "Yandex: always returned. Google: only with pay_per_indexed: true."
                    },
                    "type": {
                      "type": "string",
                      "example": "yandex/indexer"
                    },
                    "pay_per_indexed": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "task_id": "6654a1b2c3d4e5f6a7b8c9d0",
                  "pay_per_indexed": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v2/rank-tracker/limits": {
      "get": {
        "tags": [
          "Rank Tracker - reference"
        ],
        "operationId": "rtGetLimits",
        "summary": "Limits, prices and balance",
        "description": "Your account's limits and usage, current prices, balance and tokens held by running checks. Read limits from here rather than hardcoding them.",
        "responses": {
          "200": {
            "description": "Limits",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "limits": {
                      "type": "object",
                      "properties": {
                        "projects": {
                          "$ref": "#/components/schemas/LimitUsed"
                        },
                        "tracked_rows": {
                          "$ref": "#/components/schemas/LimitUsed"
                        },
                        "keywords_per_project": {
                          "type": "integer"
                        },
                        "regions_per_project": {
                          "type": "integer"
                        },
                        "tags_per_project": {
                          "type": "integer"
                        },
                        "rows_per_check": {
                          "type": "integer"
                        },
                        "keywords_per_request": {
                          "type": "integer"
                        }
                      }
                    },
                    "prices": {
                      "type": "object",
                      "properties": {
                        "page": {
                          "type": "integer",
                          "description": "Tokens per results page"
                        },
                        "page_with_ai_overview": {
                          "type": "integer",
                          "description": "Tokens for the first page with an AI Overview"
                        },
                        "promo": {
                          "$ref": "#/components/schemas/Promo"
                        }
                      }
                    },
                    "balance": {
                      "type": "integer"
                    },
                    "tokens_held": {
                      "type": "integer"
                    },
                    "depths": {
                      "type": "array",
                      "items": {
                        "type": "integer"
                      }
                    },
                    "devices": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "webhook_events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "limits": {
                    "projects": {
                      "limit": 50,
                      "used": 12
                    },
                    "tracked_rows": {
                      "limit": 100000,
                      "used": 8640
                    },
                    "keywords_per_project": 1000,
                    "regions_per_project": 5,
                    "tags_per_project": 100,
                    "rows_per_check": 50000,
                    "keywords_per_request": 10000
                  },
                  "prices": {
                    "page": 4,
                    "page_with_ai_overview": 8,
                    "promo": null
                  },
                  "balance": 250000,
                  "tokens_held": 1920,
                  "depths": [
                    10,
                    30,
                    50,
                    100
                  ],
                  "devices": [
                    "desktop"
                  ],
                  "webhook_events": [
                    "check.finished",
                    "check.failed",
                    "check.skipped"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/RtError"
          }
        }
      }
    },
    "/v2/rank-tracker/locations": {
      "get": {
        "tags": [
          "Rank Tracker - reference"
        ],
        "operationId": "rtSearchLocations",
        "summary": "Find a location",
        "description": "Google locations by the start of their name. Use canonical_name as a region's location and country_code as its gl.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "new york"
          },
          {
            "name": "gl",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 2
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Locations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "locations": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "canonical_name": {
                            "type": "string"
                          },
                          "country_code": {
                            "type": "string"
                          },
                          "target_type": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "locations": [
                    {
                      "id": 1023191,
                      "name": "New York",
                      "canonical_name": "New York,New York,United States",
                      "country_code": "us",
                      "target_type": "City"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/RtError"
          }
        }
      }
    },
    "/v2/rank-tracker/groups": {
      "get": {
        "tags": [
          "Rank Tracker - reference"
        ],
        "operationId": "rtListGroups",
        "summary": "Project groups",
        "responses": {
          "200": {
            "description": "Groups with project counts; group \"\" is the projects without a group",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "group": {
                            "type": "string"
                          },
                          "projects": {
                            "type": "integer"
                          },
                          "archived": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "items": [
                    {
                      "group": "",
                      "projects": 3,
                      "archived": 1
                    },
                    {
                      "group": "Clients",
                      "projects": 9,
                      "archived": 0
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/usage": {
      "get": {
        "tags": [
          "Rank Tracker - reference"
        ],
        "operationId": "rtGetUsage",
        "summary": "Spending",
        "description": "Tokens spent on checks by day and by project. The last 30 days by default, up to 366 days.",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "YYYY-MM-DD (midnight in tz) or an ISO time"
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tz",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "UTC"
            },
            "description": "IANA time zone of the days"
          },
          {
            "name": "group",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Spending",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "tz": {
                      "type": "string"
                    },
                    "total": {
                      "type": "object",
                      "properties": {
                        "tokens": {
                          "type": "integer"
                        },
                        "checks": {
                          "type": "integer"
                        }
                      }
                    },
                    "days": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "date": {
                            "type": "string"
                          },
                          "tokens": {
                            "type": "integer"
                          },
                          "checks": {
                            "type": "integer"
                          }
                        }
                      }
                    },
                    "projects": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "project_id": {
                            "type": "string"
                          },
                          "project_name": {
                            "type": "string"
                          },
                          "group": {
                            "type": "string"
                          },
                          "tokens": {
                            "type": "integer"
                          },
                          "checks": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/projects": {
      "get": {
        "tags": [
          "Rank Tracker - projects"
        ],
        "operationId": "rtListProjects",
        "summary": "List projects",
        "parameters": [
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "created",
                "name",
                "last_check",
                "visibility"
              ],
              "default": "created"
            }
          },
          {
            "name": "archived",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "group",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Part of the name or domain"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of projects",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Project"
                      }
                    },
                    "next_cursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/RtError"
          }
        }
      },
      "post": {
        "tags": [
          "Rank Tracker - projects"
        ],
        "operationId": "rtCreateProject",
        "summary": "Create a project",
        "description": "Creates a project, optionally with its keywords. If the keywords are refused (over a limit), the project is not created.\nSend `ref` (your own id) to make the request safe to repeat after a timeout: the same ref returns the same project with `repeated: true`.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "domain",
                  "regions"
                ],
                "properties": {
                  "domain": {
                    "type": "string",
                    "example": "example.com"
                  },
                  "regions": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "$ref": "#/components/schemas/RegionInput"
                    }
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "depth": {
                    "type": "integer",
                    "enum": [
                      10,
                      30,
                      50,
                      100
                    ],
                    "default": 30
                  },
                  "competitors": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "type": "string"
                    }
                  },
                  "schedule": {
                    "$ref": "#/components/schemas/Schedule"
                  },
                  "group": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "keywords": {
                    "$ref": "#/components/schemas/KeywordInputList"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "check_emails": {
                    "type": "boolean",
                    "default": false
                  },
                  "ref": {
                    "type": "string",
                    "maxLength": 200
                  }
                }
              },
              "example": {
                "domain": "example.com",
                "regions": [
                  {
                    "location": "New York,New York,United States",
                    "gl": "us"
                  }
                ],
                "depth": 30,
                "competitors": [
                  "competitor.com"
                ],
                "schedule": {
                  "days": [
                    1,
                    4
                  ],
                  "hour": 6,
                  "tz": "Europe/London"
                },
                "group": "Clients",
                "keywords": [
                  "pizza delivery",
                  {
                    "q": "best pizza near me",
                    "tags": [
                      "local"
                    ],
                    "target_url": "https://example.com/menu"
                  }
                ],
                "ref": "crm-4521"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Project created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectCreated"
                }
              }
            }
          },
          "200": {
            "description": "The project made earlier by a request with the same ref (repeated true)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectCreated"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/RtError"
          },
          "409": {
            "$ref": "#/components/responses/RtError"
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "get": {
        "tags": [
          "Rank Tracker - projects"
        ],
        "operationId": "rtGetProject",
        "summary": "Get a project",
        "description": "The project with its tags, removed regions, the cost of its next check, and its running and last finished checks.",
        "responses": {
          "200": {
            "description": "Project",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "project": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Project"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "past_regions": {
                              "type": "array",
                              "items": {
                                "$ref": "#/components/schemas/Region"
                              }
                            },
                            "tags": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "tag": {
                                    "type": "string"
                                  },
                                  "count": {
                                    "type": "integer"
                                  }
                                }
                              }
                            },
                            "tag_colors": {
                              "type": "object",
                              "additionalProperties": {
                                "type": "string"
                              }
                            },
                            "cost": {
                              "$ref": "#/components/schemas/Cost"
                            }
                          }
                        }
                      ]
                    },
                    "active_check": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Check"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "last_check": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Check"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  }
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/RtError"
          }
        }
      },
      "patch": {
        "tags": [
          "Rank Tracker - projects"
        ],
        "operationId": "rtUpdateProject",
        "summary": "Update a project",
        "description": "Changes the fields sent; the others stay. An archived project is not checked by its schedule until it is restored.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "depth": {
                    "type": "integer",
                    "enum": [
                      10,
                      30,
                      50,
                      100
                    ]
                  },
                  "competitors": {
                    "type": "array",
                    "maxItems": 10,
                    "items": {
                      "type": "string"
                    }
                  },
                  "group": {
                    "type": "string",
                    "maxLength": 80
                  },
                  "check_emails": {
                    "type": "boolean"
                  },
                  "schedule": {
                    "oneOf": [
                      {
                        "$ref": "#/components/schemas/Schedule"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "webhook_url": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "null or \"\" uses the account webhook"
                  },
                  "archived": {
                    "type": "boolean"
                  }
                }
              },
              "example": {
                "depth": 50,
                "schedule": {
                  "days": [
                    1,
                    2,
                    3,
                    4,
                    5
                  ],
                  "hour": 7,
                  "tz": "America/New_York"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/RtError"
          },
          "404": {
            "$ref": "#/components/responses/RtError"
          }
        }
      },
      "delete": {
        "tags": [
          "Rank Tracker - projects"
        ],
        "operationId": "rtDeleteProject",
        "summary": "Delete a project",
        "description": "Deletes the project with its keywords and history. A running check is stopped and its unspent tokens come back.",
        "responses": {
          "202": {
            "description": "Deleting",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "id": {
                      "type": "string"
                    },
                    "deleting": {
                      "type": "boolean"
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "id": "6720a1b2c3d4e5f6a7b8c9d0",
                  "deleting": true
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/RtError"
          }
        }
      }
    },
    "/v2/rank-tracker/projects/bulk": {
      "post": {
        "tags": [
          "Rank Tracker - projects"
        ],
        "operationId": "rtBulkProjects",
        "summary": "Act on many projects",
        "description": "One action for up to 500 projects; each succeeds or fails on its own. `check` queues a check of every project.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ids",
                  "action"
                ],
                "properties": {
                  "ids": {
                    "type": "array",
                    "maxItems": 500,
                    "items": {
                      "type": "string"
                    }
                  },
                  "action": {
                    "type": "string",
                    "enum": [
                      "archive",
                      "unarchive",
                      "delete",
                      "set_schedule",
                      "set_group",
                      "check"
                    ]
                  },
                  "schedule": {
                    "oneOf": [
                      {
                        "$ref": "#/components/schemas/Schedule"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "group": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "ids": [
                  "6720a1b2c3d4e5f6a7b8c9d0",
                  "6720a1b2c3d4e5f6a7b8c9ff"
                ],
                "action": "check"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Results per project",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "ok": {
                            "type": "boolean"
                          },
                          "error": {
                            "type": "string"
                          },
                          "message": {
                            "type": "string"
                          },
                          "check_id": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/projects/summary": {
      "post": {
        "tags": [
          "Rank Tracker - projects"
        ],
        "operationId": "rtProjectsSummary",
        "summary": "Status of many projects",
        "description": "A light status of up to 500 projects at once, for dashboards that poll.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "project_ids"
                ],
                "properties": {
                  "project_ids": {
                    "type": "array",
                    "maxItems": 500,
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Statuses",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "idle",
                              "checking"
                            ]
                          },
                          "archived": {
                            "type": "boolean"
                          },
                          "last_check_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "next_check_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "last_summaries": {
                            "type": "object"
                          }
                        }
                      }
                    },
                    "not_found": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/regions": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "post": {
        "tags": [
          "Rank Tracker - regions"
        ],
        "operationId": "rtAddRegion",
        "summary": "Add a region",
        "description": "Adds a region (keywords x 1 rows of the tracked rows limit). Adding a region the project had before brings its history back.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegionInput"
              },
              "example": {
                "location": "London,England,United Kingdom",
                "gl": "gb"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Region added",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "region": {
                      "$ref": "#/components/schemas/Region"
                    },
                    "project": {
                      "$ref": "#/components/schemas/Project"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/RtError"
          },
          "409": {
            "$ref": "#/components/responses/RtError"
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/regions/{region_id}": {
      "delete": {
        "tags": [
          "Rank Tracker - regions"
        ],
        "operationId": "rtRemoveRegion",
        "summary": "Remove a region",
        "description": "Removes a region; its history stays. Not the project's last region (400 last_region) and not while a check runs (409).",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "name": "region_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/RtError"
          },
          "409": {
            "$ref": "#/components/responses/RtError"
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/keywords": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "get": {
        "tags": [
          "Rank Tracker - keywords and tags"
        ],
        "operationId": "rtListKeywords",
        "summary": "List keywords",
        "description": "The project's keywords, oldest first.",
        "parameters": [
          {
            "name": "tag",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 5000,
              "default": 1000
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of keywords",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Keyword"
                      }
                    },
                    "next_cursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Rank Tracker - keywords and tags"
        ],
        "operationId": "rtAddKeywords",
        "summary": "Add keywords",
        "description": "Adds keywords. A keyword the project already has gets the new tags and the target_url if one is sent.\nA keyword that is too long or has a target_url on another domain is skipped and listed in errors; over a limit nothing is added (400).\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KeywordsBody"
              },
              "example": {
                "keywords": [
                  "pizza delivery",
                  {
                    "q": "best pizza near me",
                    "tags": [
                      "local"
                    ],
                    "target_url": "https://example.com/menu"
                  }
                ],
                "tags": [
                  "q4"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Counts per status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KeywordsResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/RtError"
          }
        }
      },
      "put": {
        "tags": [
          "Rank Tracker - keywords and tags"
        ],
        "operationId": "rtReplaceKeywords",
        "summary": "Replace the keyword list",
        "description": "Makes the project's keywords exactly the ones sent. Missing keywords are removed with their history. If any keyword is refused, nothing changes (400 invalid_keywords).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KeywordsBody"
              },
              "example": {
                "keywords": [
                  "pizza delivery",
                  "pizza near me open now"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Counts",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "added": {
                      "type": "integer"
                    },
                    "removed": {
                      "type": "integer"
                    },
                    "updated": {
                      "type": "integer"
                    },
                    "unchanged": {
                      "type": "integer"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/KeywordStatus"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/RtError"
          }
        }
      },
      "patch": {
        "tags": [
          "Rank Tracker - keywords and tags"
        ],
        "operationId": "rtEditKeywords",
        "summary": "Edit tags and target URLs",
        "description": "Adds or removes tags and sets the target URL of many keywords at once. The keyword text never changes.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ids"
                ],
                "properties": {
                  "ids": {
                    "type": "array",
                    "maxItems": 10000,
                    "items": {
                      "type": "string"
                    }
                  },
                  "add_tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "remove_tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "target_url": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "A URL on the project domain; null or \"\" removes it"
                  }
                }
              },
              "example": {
                "ids": [
                  "6720a1b2c3d4e5f6a7b8c9e0",
                  "6720a1b2c3d4e5f6a7b8c9e1"
                ],
                "add_tags": [
                  "priority"
                ],
                "remove_tags": [
                  "q4"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Matched keywords",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "matched": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/keywords/delete": {
      "post": {
        "tags": [
          "Rank Tracker - keywords and tags"
        ],
        "operationId": "rtDeleteKeywords",
        "summary": "Delete keywords",
        "description": "Deletes keywords with their history.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProjectId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "ids"
                ],
                "properties": {
                  "ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deleted count",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "deleted": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/keywords/{keyword_id}/history": {
      "get": {
        "tags": [
          "Rank Tracker - keywords and tags"
        ],
        "operationId": "rtKeywordHistory",
        "summary": "Keyword history",
        "description": "A keyword's positions and its competitors' over the region's finished checks, oldest first.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "$ref": "#/components/parameters/KeywordId"
          },
          {
            "$ref": "#/components/parameters/RegionIdQuery"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 90,
              "default": 90
            }
          }
        ],
        "responses": {
          "200": {
            "description": "History",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "region": {
                      "$ref": "#/components/schemas/Region"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "check_id": {
                            "type": "string"
                          },
                          "at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "position": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "approx": {
                            "type": "boolean"
                          },
                          "unknown": {
                            "type": "boolean"
                          },
                          "url": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "competitors": {
                            "type": "object",
                            "additionalProperties": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/tags": {
      "get": {
        "tags": [
          "Rank Tracker - keywords and tags"
        ],
        "operationId": "rtListTags",
        "summary": "List tags",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProjectId"
          }
        ],
        "responses": {
          "200": {
            "description": "Tags with keyword counts and colors",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "tag": {
                            "type": "string"
                          },
                          "count": {
                            "type": "integer"
                          },
                          "color": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/tags/rename": {
      "post": {
        "tags": [
          "Rank Tracker - keywords and tags"
        ],
        "operationId": "rtRenameTag",
        "summary": "Rename a tag",
        "description": "Renames a tag on every keyword. Renaming to an existing tag merges the two; an empty `to` removes the tag.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProjectId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "from",
                  "to"
                ],
                "properties": {
                  "from": {
                    "type": "string"
                  },
                  "to": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "from": "local",
                "to": "near me"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The project's tags",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "tags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/tags/color": {
      "post": {
        "tags": [
          "Rank Tracker - keywords and tags"
        ],
        "operationId": "rtSetTagColor",
        "summary": "Set a tag's color",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProjectId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tag",
                  "color"
                ],
                "properties": {
                  "tag": {
                    "type": "string"
                  },
                  "color": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "green",
                      "teal",
                      "blue",
                      "violet",
                      "pink",
                      "red",
                      "orange",
                      "amber",
                      "gray",
                      null
                    ]
                  }
                }
              },
              "example": {
                "tag": "brand",
                "color": "violet"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Colors by tag",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "tag_colors": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/cost": {
      "get": {
        "tags": [
          "Rank Tracker - checks"
        ],
        "operationId": "rtGetCheckCost",
        "summary": "Cost of a check",
        "description": "What the project's next check can cost, in tokens. The balance must cover cost.max.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "name": "region_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Only this region; all regions by default"
          }
        ],
        "responses": {
          "200": {
            "description": "Cost",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "cost": {
                      "$ref": "#/components/schemas/Cost"
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "cost": {
                    "min": 480,
                    "max": 1920,
                    "rows": 120,
                    "promo": null
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/checks": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ProjectId"
        }
      ],
      "post": {
        "tags": [
          "Rank Tracker - checks"
        ],
        "operationId": "rtStartCheck",
        "summary": "Run a check",
        "description": "Starts a check of all regions or one. Not enough tokens for cost.max returns 402 insufficient_balance; a check already running returns 409 already_running with its check_id.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "region_id": {
                    "type": "string"
                  }
                }
              },
              "example": {}
            }
          }
        },
        "responses": {
          "202": {
            "description": "The check, queued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckEnvelope"
                }
              }
            }
          },
          "402": {
            "$ref": "#/components/responses/RtError"
          },
          "409": {
            "$ref": "#/components/responses/RtError"
          }
        }
      },
      "get": {
        "tags": [
          "Rank Tracker - checks"
        ],
        "operationId": "rtListChecks",
        "summary": "List checks",
        "description": "The project's checks, newest first.",
        "parameters": [
          {
            "name": "region_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of checks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Check"
                      }
                    },
                    "next_cursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/checks/{check_id}": {
      "get": {
        "tags": [
          "Rank Tracker - checks"
        ],
        "operationId": "rtGetCheck",
        "summary": "Get a check",
        "description": "A check with its progress while it runs. Poll every 15-60 seconds, or wait for the webhook.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CheckId"
          }
        ],
        "responses": {
          "200": {
            "description": "Check",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckEnvelope"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/RtError"
          }
        }
      }
    },
    "/v2/rank-tracker/checks/status": {
      "post": {
        "tags": [
          "Rank Tracker - checks"
        ],
        "operationId": "rtChecksStatus",
        "summary": "Status of many checks",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "check_ids"
                ],
                "properties": {
                  "check_ids": {
                    "type": "array",
                    "maxItems": 1000,
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Checks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Check"
                      }
                    },
                    "not_found": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/checks/{check_id}/cancel": {
      "post": {
        "tags": [
          "Rank Tracker - checks"
        ],
        "operationId": "rtCancelCheck",
        "summary": "Cancel a check",
        "description": "Stops a check. What it has checked stays (partial, cancelled); unspent tokens come back. A finished check returns 409 check_finished.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CheckId"
          }
        ],
        "responses": {
          "202": {
            "description": "The check, cancel_requested true",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CheckEnvelope"
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/RtError"
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/positions": {
      "get": {
        "tags": [
          "Rank Tracker - results"
        ],
        "operationId": "rtGetPositions",
        "summary": "Positions",
        "description": "Every keyword's result in a check and region, with the change against the region's previous check. The latest finished check by default.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "$ref": "#/components/parameters/RegionIdQuery"
          },
          {
            "name": "check_id",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "latest"
            }
          },
          {
            "name": "tag",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "changed_only",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "up",
                "down",
                "new",
                "lost"
              ]
            },
            "description": "Only keywords that moved this way"
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 500
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of positions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "check": {
                      "oneOf": [
                        {
                          "$ref": "#/components/schemas/Check"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "region": {
                      "$ref": "#/components/schemas/Region"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Position"
                      }
                    },
                    "next_cursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    }
                  }
                }
              }
            }
          },
          "410": {
            "$ref": "#/components/responses/RtError"
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/trend": {
      "get": {
        "tags": [
          "Rank Tracker - results"
        ],
        "operationId": "rtGetTrend",
        "summary": "Trend",
        "description": "A region's summary over its last 90 finished checks, oldest first.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "$ref": "#/components/parameters/RegionIdQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Trend",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "region": {
                      "$ref": "#/components/schemas/Region"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "allOf": [
                          {
                            "type": "object",
                            "properties": {
                              "check_id": {
                                "type": "string"
                              },
                              "at": {
                                "type": "string",
                                "format": "date-time"
                              },
                              "partial": {
                                "type": "boolean"
                              },
                              "depth": {
                                "type": "integer"
                              }
                            }
                          },
                          {
                            "$ref": "#/components/schemas/Summary"
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/checks/{check_id}/keywords/{keyword_id}": {
      "get": {
        "tags": [
          "Rank Tracker - results"
        ],
        "operationId": "rtGetKeywordDetails",
        "summary": "Keyword in a check",
        "description": "One keyword's result in a finished check with the top 10 domains and the AI Overview (sources, whether the site is cited and how). The full overview text (blocks) is kept for the region's latest check only.",
        "parameters": [
          {
            "$ref": "#/components/parameters/CheckId"
          },
          {
            "$ref": "#/components/parameters/KeywordId"
          },
          {
            "$ref": "#/components/parameters/RegionIdQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Keyword result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "check_id": {
                      "type": "string"
                    },
                    "region": {
                      "$ref": "#/components/schemas/Region"
                    },
                    "keyword": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Position"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "top10": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      ]
                    },
                    "ai_overview": {
                      "oneOf": [
                        {
                          "type": "null"
                        },
                        {
                          "type": "object",
                          "properties": {
                            "present": {
                              "type": "boolean"
                            },
                            "cited": {
                              "type": "boolean"
                            },
                            "mentioned": {
                              "type": "boolean"
                            },
                            "place": {
                              "type": [
                                "integer",
                                "null"
                              ]
                            },
                            "url": {
                              "type": [
                                "string",
                                "null"
                              ]
                            },
                            "quotes": {
                              "type": "array",
                              "items": {
                                "type": "string"
                              }
                            },
                            "sources": {
                              "type": "array",
                              "items": {
                                "type": "object",
                                "properties": {
                                  "url": {
                                    "type": "string"
                                  },
                                  "host": {
                                    "type": "string"
                                  },
                                  "title": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "name": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  },
                                  "owner": {
                                    "type": [
                                      "string",
                                      "null"
                                    ]
                                  }
                                }
                              }
                            },
                            "blocks": {
                              "description": "Full overview text while this is the region's latest check; null after"
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/projects/{project_id}/export": {
      "get": {
        "tags": [
          "Rank Tracker - results"
        ],
        "operationId": "rtExport",
        "summary": "Export positions",
        "description": "All positions of a check and region in one streamed file, CSV (UTF-8 with BOM) or JSON. At most 2 exports at once per account (429 too_many_heavy_requests).",
        "parameters": [
          {
            "$ref": "#/components/parameters/ProjectId"
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "csv",
                "json"
              ],
              "default": "csv"
            }
          },
          {
            "name": "check_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RegionIdQuery"
          },
          {
            "name": "tag",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The export file",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RtError"
          }
        }
      }
    },
    "/v2/rank-tracker/webhook": {
      "get": {
        "tags": [
          "Rank Tracker - webhooks"
        ],
        "operationId": "rtGetWebhook",
        "summary": "Get the webhook",
        "responses": {
          "200": {
            "description": "The account webhook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEnvelope"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Rank Tracker - webhooks"
        ],
        "operationId": "rtSetWebhook",
        "summary": "Set the webhook",
        "description": "Sets the URL and events. The first time, the response has the signing `secret`; store it, it is not shown again.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "A public https URL"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "check.finished",
                        "check.failed",
                        "check.skipped"
                      ]
                    },
                    "description": "None or [] for all"
                  }
                }
              },
              "example": {
                "url": "https://hooks.example.com/speedyindex",
                "events": [
                  "check.finished",
                  "check.failed"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook (and the secret the first time)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/WebhookEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "secret": {
                          "type": "string",
                          "description": "whsec_..., the first time only"
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Rank Tracker - webhooks"
        ],
        "operationId": "rtDeleteWebhook",
        "summary": "Remove the webhook",
        "description": "Stops the account's events. Projects with their own webhook_url still get theirs. The secret stays.",
        "responses": {
          "200": {
            "description": "Webhook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/webhook/secret": {
      "post": {
        "tags": [
          "Rank Tracker - webhooks"
        ],
        "operationId": "rtRotateWebhookSecret",
        "summary": "Rotate the secret",
        "description": "Makes a new signing secret. For 24 hours events are signed with both, newest first.",
        "responses": {
          "200": {
            "description": "New secret",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/WebhookEnvelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "secret": {
                          "type": "string"
                        }
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/webhook/test": {
      "post": {
        "tags": [
          "Rank Tracker - webhooks"
        ],
        "operationId": "rtTestWebhook",
        "summary": "Send a test event",
        "description": "Sends a signed webhook.test event now and returns how your server replied.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Another URL to test; the account's by default"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Delivery result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "delivery": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "event_id": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string"
                        },
                        "ok": {
                          "type": "boolean"
                        },
                        "status": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "error": {
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/webhook/deliveries": {
      "get": {
        "tags": [
          "Rank Tracker - webhooks"
        ],
        "operationId": "rtListDeliveries",
        "summary": "Deliveries",
        "description": "Events sent in the last 7 days, newest first, with their state.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of deliveries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "event_id": {
                            "type": "string"
                          },
                          "event": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string"
                          },
                          "state": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "sending",
                              "done",
                              "failed"
                            ]
                          },
                          "attempts": {
                            "type": "integer"
                          },
                          "last_status": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "last_error": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "delivered_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "next_at": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "project_id": {
                            "type": "string"
                          },
                          "check_id": {
                            "type": "string"
                          },
                          "payload": {
                            "type": "object"
                          }
                        }
                      }
                    },
                    "next_cursor": {
                      "$ref": "#/components/schemas/NextCursor"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/rank-tracker/webhook/deliveries/{delivery_id}/redeliver": {
      "post": {
        "tags": [
          "Rank Tracker - webhooks"
        ],
        "operationId": "rtRedeliver",
        "summary": "Send a delivery again",
        "description": "Sends an event again with the same event_id; retries start anew.",
        "parameters": [
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Queued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "$ref": "#/components/schemas/Code"
                    },
                    "id": {
                      "type": "string"
                    },
                    "state": {
                      "type": "string",
                      "const": "pending"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "check.finished": {
      "post": {
        "operationId": "onCheckFinished",
        "summary": "A check is done (cancelled and partial ones too)",
        "description": "Sent as a POST with a JSON body to your https URL. Any 2xx within 10 seconds is a delivery; otherwise it is retried after 1, 5 and 30 minutes.\nAn event may arrive more than once: process each event_id once.\n`X-SpeedyIndex-Signature` is `sha256=` plus the hex HMAC-SHA256 of the raw body with your webhook secret; during a rotation it has two comma-separated signatures, the new one first.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckFinishedEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          }
        }
      }
    },
    "check.failed": {
      "post": {
        "operationId": "onCheckFailed",
        "summary": "A check failed",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event_id": {
                    "type": "string"
                  },
                  "event": {
                    "type": "string",
                    "const": "check.failed"
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "project_id": {
                    "type": "string"
                  },
                  "project_name": {
                    "type": "string"
                  },
                  "group": {
                    "type": "string"
                  },
                  "check_id": {
                    "type": "string"
                  },
                  "trigger": {
                    "type": "string"
                  },
                  "error": {
                    "type": "string"
                  },
                  "tokens_spent": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          }
        }
      }
    },
    "check.skipped": {
      "post": {
        "operationId": "onCheckSkipped",
        "summary": "A scheduled check did not run",
        "description": "reason is insufficient_balance (with its check_id), still_running or serp_unavailable.",
        "parameters": [
          {
            "$ref": "#/components/parameters/WebhookSignature"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event_id": {
                    "type": "string"
                  },
                  "event": {
                    "type": "string",
                    "const": "check.skipped"
                  },
                  "created_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "project_id": {
                    "type": "string"
                  },
                  "project_name": {
                    "type": "string"
                  },
                  "group": {
                    "type": "string"
                  },
                  "reason": {
                    "type": "string",
                    "enum": [
                      "insufficient_balance",
                      "still_running",
                      "serp_unavailable"
                    ]
                  },
                  "check_id": {
                    "type": "string"
                  },
                  "scheduled_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Received"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "Authorization",
        "description": "Your SpeedyIndex API key, sent as it is (no Bearer prefix)."
      }
    },
    "parameters": {
      "SearchEngine": {
        "name": "search_engine",
        "in": "path",
        "required": true,
        "description": "google, yandex or bing (bing supports checker only)",
        "example": "google",
        "schema": {
          "type": "string",
          "enum": [
            "google",
            "yandex",
            "bing"
          ]
        }
      },
      "TaskType": {
        "name": "task_type",
        "in": "path",
        "required": true,
        "description": "indexer (submit for indexing) or checker (index status check)",
        "example": "indexer",
        "schema": {
          "type": "string",
          "enum": [
            "indexer",
            "checker"
          ]
        }
      },
      "ProjectId": {
        "name": "project_id",
        "in": "path",
        "required": true,
        "example": "6720a1b2c3d4e5f6a7b8c9d0",
        "schema": {
          "type": "string",
          "pattern": "^[0-9a-f]{24}$"
        }
      },
      "CheckId": {
        "name": "check_id",
        "in": "path",
        "required": true,
        "example": "6720b4f0c3d4e5f6a7b8ca01",
        "schema": {
          "type": "string",
          "pattern": "^[0-9a-f]{24}$"
        }
      },
      "KeywordId": {
        "name": "keyword_id",
        "in": "path",
        "required": true,
        "example": "6720a1b2c3d4e5f6a7b8c9e0",
        "schema": {
          "type": "string",
          "pattern": "^[0-9a-f]{24}$"
        }
      },
      "RegionIdQuery": {
        "name": "region_id",
        "in": "query",
        "description": "A current or removed region (its history stays); the project's first region by default.",
        "schema": {
          "type": "string"
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "description": "next_cursor of the previous page. Opaque; only next_cursor null means the end.",
        "schema": {
          "type": "string"
        }
      },
      "WebhookSignature": {
        "name": "X-SpeedyIndex-Signature",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "example": "sha256=5f2b..."
        }
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "The API key is missing or wrong",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InsufficientBalance": {
        "description": "Not enough balance",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "PayloadTooLarge": {
        "description": "The request body is too large",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded; wait for Retry-After seconds",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RtError": {
        "description": "Rank Tracker error. `error` is a stable name to branch on, for example invalid_domain, projects_limit,\narchived, no_api_key, invalid_api_key, insufficient_balance, project_not_found, already_running,\nref_conflict, ref_in_progress, check_finished, rows_expired, body_too_large, rate_limited,\ntoo_many_heavy_requests, internal_error, serp_unavailable.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": 10,
              "error": "already_running",
              "message": "A check of this project is running",
              "check_id": "6720b4f0c3d4e5f6a7b8ca01"
            }
          }
        }
      }
    },
    "schemas": {
      "Code": {
        "type": "integer",
        "description": "0 on success; non-zero on error."
      },
      "Error": {
        "type": "object",
        "properties": {
          "code": {
            "type": "integer"
          },
          "error": {
            "type": "string",
            "description": "Machine-readable error name (Rank Tracker)"
          },
          "message": {
            "type": "string"
          }
        },
        "additionalProperties": true
      },
      "TaskIdBody": {
        "type": "object",
        "required": [
          "task_id"
        ],
        "properties": {
          "task_id": {
            "type": "string"
          }
        }
      },
      "TaskIdOrIds": {
        "type": "object",
        "properties": {
          "task_id": {
            "type": "string",
            "description": "A single task id (required if task_ids is not sent)"
          },
          "task_ids": {
            "type": "array",
            "maxItems": 1000,
            "items": {
              "type": "string"
            },
            "description": "Up to 1000 task ids (required if task_id is not sent)"
          }
        }
      },
      "Task": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "size": {
            "type": "integer",
            "description": "Total URLs in the task"
          },
          "processed_count": {
            "type": "integer"
          },
          "indexed_count": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "is_completed": {
            "type": "boolean"
          },
          "type": {
            "type": "string",
            "example": "google/indexer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "pay_per_indexed": {
            "type": "boolean",
            "description": "Pay per Indexed tasks only"
          },
          "status": {
            "type": "string",
            "description": "Pay per Indexed tasks only"
          },
          "tokens_charged": {
            "type": "integer",
            "description": "Pay per Indexed tasks only"
          },
          "tokens_refunded": {
            "type": "integer",
            "description": "Pay per Indexed tasks only"
          },
          "check_after": {
            "type": "string",
            "format": "date-time",
            "description": "Pay per Indexed tasks only. When the final index check runs."
          },
          "days": {
            "type": "integer",
            "description": "Drip Feed tasks only"
          },
          "days_passed": {
            "type": "integer",
            "description": "Drip Feed tasks only"
          },
          "is_stopped": {
            "type": "boolean",
            "description": "Drip Feed tasks only"
          },
          "child_task_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Drip Feed tasks only"
          },
          "children": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Task"
            },
            "description": "Drip Feed, single task_id only"
          }
        }
      },
      "ReportBase": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "processed_count": {
            "type": "integer"
          },
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "pay_per_indexed": {
            "type": "boolean"
          },
          "tokens_charged": {
            "type": "integer"
          },
          "tokens_refunded": {
            "type": "integer"
          },
          "drip_feed": {
            "type": "boolean"
          },
          "days": {
            "type": "integer"
          },
          "days_passed": {
            "type": "integer"
          }
        }
      },
      "BacklinkTask": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "processed_count": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "target_domains": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "is_completed": {
            "type": "boolean"
          },
          "type": {
            "type": "string",
            "const": "backlink/checker"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Donor": {
        "type": "object",
        "properties": {
          "donor_url": {
            "type": "string",
            "format": "uri"
          },
          "processed": {
            "type": "boolean"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "http_status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "redirect_chain": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "canonical_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "page_language": {
            "type": [
              "string",
              "null"
            ]
          },
          "moz_domain_authority": {
            "type": [
              "integer",
              "null"
            ]
          },
          "moz_spam_score": {
            "type": [
              "integer",
              "null"
            ]
          },
          "internal_links_count": {
            "type": [
              "integer",
              "null"
            ]
          },
          "external_links_count": {
            "type": [
              "integer",
              "null"
            ]
          },
          "indexing": {
            "type": "object",
            "description": "Whether search engines may index the page, by engine"
          },
          "target_links": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string"
                },
                "anchor": {
                  "type": "string"
                },
                "anchor_type": {
                  "type": "string"
                },
                "nofollow": {
                  "type": "boolean"
                },
                "is_ugc": {
                  "type": "boolean"
                },
                "is_sponsored": {
                  "type": "boolean"
                }
              }
            }
          }
        }
      },
      "LimitUsed": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "integer"
          },
          "used": {
            "type": "integer"
          }
        }
      },
      "Promo": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "discount": {
            "type": "number"
          },
          "until": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Cost": {
        "type": "object",
        "properties": {
          "min": {
            "type": "integer",
            "description": "One results page per row"
          },
          "max": {
            "type": "integer",
            "description": "Held from the balance when the check starts"
          },
          "rows": {
            "type": "integer",
            "description": "Keywords x regions"
          },
          "promo": {
            "$ref": "#/components/schemas/Promo"
          }
        }
      },
      "NextCursor": {
        "type": [
          "string",
          "null"
        ],
        "description": "Pass as cursor for the next page; null means the end."
      },
      "Schedule": {
        "type": "object",
        "required": [
          "days",
          "hour"
        ],
        "properties": {
          "days": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 0,
              "maximum": 6
            },
            "description": "Days of the week, 0 is Sunday"
          },
          "hour": {
            "type": "integer",
            "minimum": 0,
            "maximum": 23
          },
          "tz": {
            "type": "string",
            "description": "IANA time zone, e.g. Europe/London"
          }
        }
      },
      "RegionInput": {
        "type": "object",
        "required": [
          "location",
          "gl"
        ],
        "properties": {
          "location": {
            "type": "string",
            "description": "canonical_name from GET /v2/rank-tracker/locations"
          },
          "gl": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          },
          "device": {
            "type": "string",
            "enum": [
              "desktop"
            ],
            "default": "desktop"
          }
        }
      },
      "Region": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "location": {
            "type": "string"
          },
          "gl": {
            "type": "string"
          },
          "device": {
            "type": "string"
          },
          "google_domain": {
            "type": "string"
          },
          "label": {
            "type": "string"
          }
        }
      },
      "Summary": {
        "type": "object",
        "description": "A region's totals in a check. Keywords whose page failed to load are left out of every metric.",
        "properties": {
          "total": {
            "type": "integer"
          },
          "known": {
            "type": [
              "integer",
              "null"
            ]
          },
          "found": {
            "type": "integer"
          },
          "visibility": {
            "type": "number",
            "description": "0-100%: position 1 counts 100%, 2 85%, 3 60%, 4-5 50%, 6-7 30%, 8-10 20%, 11-20 10%, 21-50 5%"
          },
          "avg_position": {
            "type": [
              "number",
              "null"
            ]
          },
          "top3": {
            "type": "integer"
          },
          "top10": {
            "type": "integer"
          },
          "ai_present": {
            "type": [
              "integer",
              "null"
            ]
          },
          "ai_cited": {
            "type": [
              "integer",
              "null"
            ]
          },
          "distribution": {
            "type": "object",
            "properties": {
              "top3": {
                "type": "integer"
              },
              "top10": {
                "type": "integer"
              },
              "top20": {
                "type": "integer"
              },
              "top50": {
                "type": "integer"
              },
              "top100": {
                "type": "integer"
              },
              "not_found": {
                "type": "integer"
              }
            }
          }
        }
      },
      "Project": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "domain": {
            "type": "string"
          },
          "group": {
            "type": "string"
          },
          "ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "api",
              "cabinet"
            ]
          },
          "depth": {
            "type": "integer",
            "enum": [
              10,
              30,
              50,
              100
            ]
          },
          "competitors": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "regions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Region"
            }
          },
          "schedule": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Schedule"
              },
              {
                "type": "null"
              }
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "idle",
              "checking"
            ]
          },
          "archived": {
            "type": "boolean"
          },
          "keywords_count": {
            "type": "integer"
          },
          "last_check_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "next_check_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_summaries": {
            "type": "object",
            "description": "By region id",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "check_id": {
                  "type": "string"
                },
                "at": {
                  "type": "string",
                  "format": "date-time"
                },
                "summary": {
                  "$ref": "#/components/schemas/Summary"
                },
                "change": {
                  "type": "object"
                }
              }
            }
          },
          "last_skipped": {
            "type": [
              "object",
              "null"
            ]
          },
          "webhook_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "check_emails": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ProjectEnvelope": {
        "type": "object",
        "properties": {
          "code": {
            "$ref": "#/components/schemas/Code"
          },
          "project": {
            "$ref": "#/components/schemas/Project"
          }
        }
      },
      "ProjectCreated": {
        "type": "object",
        "properties": {
          "code": {
            "$ref": "#/components/schemas/Code"
          },
          "project": {
            "$ref": "#/components/schemas/Project"
          },
          "keywords": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/KeywordsResult"
              },
              {
                "type": "null"
              }
            ]
          },
          "repeated": {
            "type": "boolean"
          }
        }
      },
      "Check": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "project_id": {
            "type": "string"
          },
          "trigger": {
            "type": "string",
            "enum": [
              "manual",
              "schedule",
              "queued"
            ]
          },
          "source": {
            "type": "string",
            "enum": [
              "api",
              "cabinet"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "done",
              "failed"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "partial": {
            "type": "boolean"
          },
          "cancelled": {
            "type": "boolean"
          },
          "cancel_requested": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "started_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "finished_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "depth": {
            "type": "integer"
          },
          "rows": {
            "type": "integer"
          },
          "regions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Region"
            }
          },
          "summaries": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/Summary"
            }
          },
          "tokens_spent": {
            "type": "integer"
          },
          "tokens_held": {
            "type": [
              "integer",
              "null"
            ]
          },
          "progress": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "keywords": {
                "type": "integer"
              },
              "wave": {
                "type": "integer"
              },
              "wave_keywords": {
                "type": "integer"
              },
              "wave_done": {
                "type": "integer"
              },
              "retry": {
                "type": "boolean"
              },
              "retry_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "failed_pages": {
                "type": "integer"
              },
              "eta_sec": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "rows_expire_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "CheckEnvelope": {
        "type": "object",
        "properties": {
          "code": {
            "$ref": "#/components/schemas/Code"
          },
          "check": {
            "$ref": "#/components/schemas/Check"
          }
        }
      },
      "KeywordInputList": {
        "type": "array",
        "maxItems": 10000,
        "items": {
          "oneOf": [
            {
              "type": "string",
              "maxLength": 300
            },
            {
              "type": "object",
              "required": [
                "q"
              ],
              "properties": {
                "q": {
                  "type": "string",
                  "maxLength": 300
                },
                "tags": {
                  "type": "array",
                  "maxItems": 10,
                  "items": {
                    "type": "string",
                    "maxLength": 40
                  }
                },
                "target_url": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          ]
        }
      },
      "KeywordsBody": {
        "type": "object",
        "required": [
          "keywords"
        ],
        "properties": {
          "keywords": {
            "$ref": "#/components/schemas/KeywordInputList"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "KeywordStatus": {
        "type": "object",
        "properties": {
          "index": {
            "type": "integer"
          },
          "id": {
            "type": "string"
          },
          "q": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "added",
              "updated",
              "unchanged",
              "skipped"
            ]
          }
        }
      },
      "KeywordsResult": {
        "type": "object",
        "properties": {
          "code": {
            "$ref": "#/components/schemas/Code"
          },
          "added": {
            "type": "integer"
          },
          "updated": {
            "type": "integer"
          },
          "skipped": {
            "type": "integer"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "index": {
                  "type": "integer"
                },
                "q": {
                  "type": "string"
                },
                "error": {
                  "type": "string",
                  "enum": [
                    "too_long",
                    "invalid_target_url"
                  ]
                }
              }
            }
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KeywordStatus"
            }
          }
        }
      },
      "Keyword": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "q": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "target_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Position": {
        "type": "object",
        "properties": {
          "keyword_id": {
            "type": "string"
          },
          "q": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "target_url": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "checked",
              "pending",
              "not_checked"
            ]
          },
          "position": {
            "type": [
              "integer",
              "null"
            ]
          },
          "found": {
            "type": "boolean"
          },
          "unknown": {
            "type": "boolean"
          },
          "approx": {
            "type": "boolean"
          },
          "url": {
            "type": [
              "string",
              "null"
            ]
          },
          "urls": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string"
                },
                "position": {
                  "type": "integer"
                }
              }
            }
          },
          "prev_position": {
            "type": [
              "integer",
              "null"
            ]
          },
          "prev_found": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "change": {
            "type": [
              "integer",
              "null"
            ]
          },
          "movement": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "up",
              "down",
              "same",
              "new",
              "lost",
              null
            ]
          },
          "competitors": {
            "type": [
              "object",
              "null"
            ]
          },
          "features": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "string"
            }
          },
          "ai_present": {
            "type": "boolean"
          },
          "ai_cited": {
            "type": "boolean"
          },
          "snippet_own": {
            "type": "boolean"
          },
          "snippet_owner": {
            "type": [
              "string",
              "null"
            ]
          },
          "wrong_url": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "cannibal": {
            "type": [
              "boolean",
              "null"
            ]
          },
          "compact": {
            "type": "boolean"
          }
        }
      },
      "WebhookEnvelope": {
        "type": "object",
        "properties": {
          "code": {
            "$ref": "#/components/schemas/Code"
          },
          "webhook": {
            "type": "object",
            "properties": {
              "url": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "events": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "has_secret": {
                "type": "boolean"
              },
              "previous_secret_valid_until": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          }
        }
      },
      "CheckFinishedEvent": {
        "type": "object",
        "properties": {
          "event_id": {
            "type": "string"
          },
          "event": {
            "type": "string",
            "const": "check.finished"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "project_id": {
            "type": "string"
          },
          "project_name": {
            "type": "string"
          },
          "group": {
            "type": "string"
          },
          "project_ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "check_id": {
            "type": "string"
          },
          "trigger": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "partial": {
            "type": "boolean"
          },
          "cancelled": {
            "type": "boolean"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "summaries": {
            "type": "object"
          },
          "tokens_spent": {
            "type": "integer"
          },
          "finished_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      }
    }
  }
}