Документация API

Документация API

Адрес API: https://2index.ninja/api/v1/

Для выполнения запроса к API нужно передать Bearer токен доступа в заголовке Authorization.

curl https://2index.ninja/api/v1/account -H "Authorization: Bearer API_TOKEN"

Токен доступа можно получить в соответствующем разделе в кабинете пользователя.

В ответе на каждый запрос присутсвует параметр success, по которому определяется успешность запроса.
Параметр errors содержит сообщения об ошибках.

В некоторых случаях, если будет возвращаться ошибка 403, необходимо указать user-agent, например:

curl https://2index.ninja/api/v1/account -H "Authorization: Bearer API_TOKEN" -A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"

Запросы могут быть ограничены со стороны хостинга, в этом случае мы рекомендуем использовать прокси.

Методы для работы с аккаунтом

Получить данные аккаунта

Нужно выполнить GET запрос по адресу account

GET https://2index.ninja/api/v1/account

В ответ будут получены данные в формате JSON:

{
    "success": true,
    "account": {
        "email": "[email protected]",
        "tariff": "White Ninja",
        "balance": 100.0,
        "available_projects": 1,
        "available_links": 100,
        "available_indexation_check_links": 500,
        "link_sending_speed": 100,
        "tariff_available": true,
        "tariff_expiring_date": "2025-01-16T14:26:11.000000Z",
        "email_verified": false,
        "link_cost": "$0.00056"
    }
}

Методы для работы с проектами

Получить список проектов

Нужно выполнить GET запрос по адресу project

GET https://2index.ninja/api/v1/project

В ответ будут получены данные в формате JSON:

{
    "success": true,
    "projects": [
        {
            "id": 1,
            "name": "Project name",
            "type": "indexing",
            "website": "https://domain.com/",
            "status": "in progress",
            "created_at": "2024-03-01 14:34:56",
            "links_type": "internal",
            "google_account_access_granted": 0,
            "links_total": 500,
            "links_sending_speed": 400,
            "links_sent_google": 100,
            "links_sent_yandex": 40,
            "links_sent_bing": 100,
            "in_queue": 360,
            "sent_links": 100,
            "indexed": 30,
            "not_indexed": 0,
            "download_queue_url": "DOWNLOAD_QUEUE_URL",
            "download_sent_url": "DOWNLOAD_SENT_URL",
            "download_indexed_url": "DOWNLOAD_INDEXED_URL",
            "download_unindexed_url": "DOWNLOAD_UNINDEXED_URL"
        },
        {
            "id": "2",
            "name": "Project 2 name",
            "type": "indexing_check",
            "status": "in progress",
            "created_at": "2024-03-01 14:34:56",
            "links_total": 200,
            "links_checking_speed": 100,
            "in_queue": 100,
            "checked": 100,
            "indexed": 70,
            "not_indexed": 30,
            "download_queue_url": "DOWNLOAD_QUEUE_URL",
            "download_indexed_url": "DOWNLOAD_INDEXED_URL",
            "download_unindexed_url": "DOWNLOAD_UNINDEXED_URL",
            "download_all_url": "DOWNLOAD_ALL_URL",
            "download_checked_url": "DOWNLOAD_CHECKED_URL",
        }
        ...
    ]
}

Получить данные проекта

Нужно выполнить GET запрос по адресу project/{project_id}

GET https://2index.ninja/api/v1/project/1

В ответ будут получены данные в формате JSON:

  • Для проекта индексации:
{
    "success": true,
    "project": {
        "id": 1,
        "name": "Project name",
        "type": "indexing",
        "website": "https://domain.com/",
        "status": "in progress",
        "created_at": "2024-03-01 14:34:56",
        "links_type": "internal",
        "google_account_access_granted": 0,
        "links_total": 500,
        "links_sending_speed": 400,
        "links_sent_google": 100,
        "links_sent_yandex": 40,
        "links_sent_bing": 100,
        "in_queue": 360,
        "sent_links": 100,
        "indexed": 30,
        "not_indexed": 0,
        "download_queue_url": "DOWNLOAD_QUEUE_URL",
        "download_sent_url": "DOWNLOAD_SENT_URL",
        "download_indexed_url": "DOWNLOAD_INDEXED_URL",
        "download_unindexed_url": "DOWNLOAD_UNINDEXED_URL"
    }
}
  • Для проекта проверки индексации:
{
    "success": true,
    "project": {
        "id": "2",
        "name": "Project 2 name",
        "type": "indexing_check",
        "status": "in progress",
        "created_at": "2024-03-01 14:34:56",
        "links_total": 200,
        "links_checking_speed": 100,
        "in_queue": 100,
        "checked": 100,
        "indexed": 70,
        "not_indexed": 30,
        "download_queue_url": "DOWNLOAD_QUEUE_URL",
        "download_indexed_url": "DOWNLOAD_INDEXED_URL",
        "download_unindexed_url": "DOWNLOAD_UNINDEXED_URL",
        "download_all_url": "DOWNLOAD_ALL_URL",
        "download_checked_url": "DOWNLOAD_CHECKED_URL"
    }
}

Создать проект

Нужно выполнить POST запрос по адресу project

POST https://2index.ninja/api/v1/project

Параметры запроса:

Поле Тип Обязательно Описание
name string да Название проекта
website string да* Адрес сайта в формате https://site.domain/.
*Обязателен если тип проекта: indexing
for_external_links boolean нет Проект для внешних ссылок. Если не указано, будет только для внутренних.
indexing_speed integer нет** Скорость индексации проекта, если не указано будет применена вся доступная скорость на аккаунте. Используется для проектов с типом indexing. Для проектов с типом indexing_check используется checking_speed
checking_speed integer нет** Скорость проверки ссылок проекта, если не указано будет применена вся доступная скорость на аккаунте. Используется для проектов с типом indexing_check. Для проектов с типом indexing используется indexing_speed
type string нет Тип проекта.
Возможные варианты: indexing - индексация ссылок, indexing_check - проверка индексации ссылок.
Если не указано - создаст проект индексации сыслок indexing

** При создании проекта любого типа можно использовать любое из параметров indexing_speed и checking_speed они являются алиасами друг для друга, но если переданы оба, будет использоваться indexing_speed.

В ответ будут получены данные в формате JSON:

{
    "success": true,
    "message": "The project has been successfully created"
}

Пример создания проекта индексации ссылок:
POST https://2index.ninja/api/v1/project

name: Project 1
website: https://website.com
for_external_links: 1
indexing_speed: 100

Пример создания проекта проверки индексации ссылок:
POST https://2index.ninja/api/v1/project

name: Project 2
checking_speed: 100

Очистить очередь индексации

Нужно выполнить POST запрос по адресу project/{project_id}/clear_queue

POST https://2index.ninja/api/v1/project/1/clear_queue

В ответ будут получены данные в формате JSON:

{
    "success": true,
    "message": "The indexing queue has been cleared successfully. X links have been removed"
}

Либо будет возвращено соответсвующее сообщение об ошибке:

{
    "success": false,
    "errors": ["Project not found"]
}

Методы для работы со ссылками

Добавить ссылки

Нужно выполнить POST запрос по адресу link/add

POST https://2index.ninja/api/v1/link/add

Параметры запроса:

Поле Обязательно Описание
project_id да ID проекта
links да Список ссылок. Можно передать в виде массива ссылок или в виде текста (каждая ссылка отдельной строкой)
google нет, при условии yandex или bing Отправлять ссылки в Google
yandex нет, при условии google или bing Отправлять ссылки в Yandex
bing нет, при условии google или yandex Отправлять ссылки в Bing
google_access_granted нет Предоставлен доступ к аккаунту Google

В ответ будут получены данные в формате JSON:

{
    "success": true,
    "message": "Links have been successfully added to the project"
}

Если в списке будут ошибочные ссылки, ссылки не будут добавлены, в ответ будет получено соответсвующее сообщение об ошибке:

{
    "success": false,
    "errors": ["You sent invalid links"],
    "invalid_links": ["http://wrong.link"]
}

Для проектов проверки индексации ссылки добавляются точно также как и для индексации, google_access_granted - не обязательно передавать, будет игнорироваться. Поисковые системы нужно указать, но на данный момент доступна проверка только в google.

Добавить ссылки по названию проекта

Нужно выполнить POST запрос по адресу link/add_simple. Если проекта с указанным именем не существует, он будет создан автоматически с максимальной скоростью отправки.

POST https://2index.ninja/api/v1/link/add_simple

Параметры запроса:

Поле Обязательно Описание
project_name нет Название проекта. Если не указано, будет создан проект с именем "default".
links да Список ссылок. Можно передать массивом или текстом (каждая ссылка с новой строки).
google нет, если указан yandex или bing Отправлять ссылки в Google.
yandex нет, если указан google или bing Отправлять ссылки в Yandex.
bing нет, если указан google или yandex Отправлять ссылки в Bing.
google_access_granted нет Предоставлен доступ к аккаунту Google.

Для проектов проверки индексации ссылки добавляются точно также как и для индексации, google_access_granted - не обязательно передавать, будет игнорироваться. Поисковые системы нужно указать, но на данный момент доступна проверка только в google.

Пример запроса:

{
    "project_name": "My Website",
    "links": ["https://example.com/page1", "https://example.com/page2"],
    "google": true,
    "yandex": false,
    "bing": true,
    "google_access_granted": false
}

Ответ в случае успеха:

{
    "success": true,
    "message": "Links have been successfully added to the project",
    "project_name": "My Website",
    "project_id": 12345
}

Возможные ошибки:

  • Если в списке будут ошибочные ссылки:
{
    "success": false,
    "errors": ["You sent invalid links"],
    "invalid_links": ["http://wrong.link"]
}
  • Если произошла ошибка при создании проекта:
{
    "success": false,
    "errors": ["Failed to create the project"]
}

Проверить статус ссылки

Выполните POST запрос по адресу /api/v1/link/status

POST https://2index.ninja/api/v1/link/status

Параметры запроса:

Поле Обязательно Описание
project_id да ID проекта
link да Проверяемая ссылка
  • При успешном запросе в ответ будет получен json объект:
{
    "success": true,
    "link": {
        "id": 34368960,
        "url": "https://2index.ninja/",
        "google": "Sent",
        "yandex": "Sent",
        "bing": "Sent",
        "is_external": 1,
        "google_sent": "2025-08-24 20:10:02",
        "yandex_sent": "2025-08-24 20:45:02",
        "bing_sent": "2025-08-24 20:05:05",
        "google_indexed": 1,
        "google_indexing_check_date": "2025-08-29"
    }
}

Где:

Поле Описание
id ID ссылки
url Ссылка
google * Статус отправки в Google
yandex * Статус отправки в Yandex
bing * Статус отправки в Bing
is_external Внешняя ссылка
google_sent Дата отправки в Google
yandex_sent Дата отправки в Yandex
bing_sent Дата отправки в Bing
google_indexed Проиндексировано в Google
google_indexing_check_date Дата проверки индексации в Goolge

* Возможные статусы:

Статус Значение
New Новая
Sent Отправлена
In the queue В очереди отправки
In the process В процессе отправки
Error sending Произошла ошибка при отправке
Don\'t index Не индексировать
Sent to reindexing Отправлена на переиндексацию
  • Если произошла ошибка будет возвращен JSON объект с сообщением об ошибке. Примеры ошибок:
{
    "success": false,
    "errors":{
        "link": [
            "The link field is required."
        ]
    }
}
{
    "success": false,
    "errors":[
        "Project not found"
    ]
}
{
    "success": false,
    "errors":[
        "URL not found"
    ]
}

Также можно получить статус ссылки по ID ссылки

Для этого выполните GET запрос по адресу /api/v1/link/status/ID

GET https://2index.ninja/api/v1/link/status/ID

Ответ на запрос будет таким же как и в предыдущем варианте

Отправить ссылки на переиндексацию

Отправляет непроиндексированные ссылки на переиндексацию. Принимает параметр max_attempts для ограничения максимального к-ва переотправок ссылок (от 1 до 10). Принимает массив ссылок links для переотправки на индексацию, если ссылки не переданы то получает все непроиндексированные ссылки из проекта. Далее проверяет к-во отправок ссылок и после проверки пытается добавить ссылки в проект, учитывая лимиты аккаунта. Если переданы ссылки, которые не отправлялись, они тоже будут добавлены в очередь.

Выполните POST запрос по адресу /api/v1/link/resent_notindexed_links/{project_id}

POST https://2index.ninja/api/v1/link/resent_notindexed_links/{project_id}

Параметры запроса:

Поле Обязательно Описание
project_id да ID проекта
max_attempts да (от 1 до 10) Лимит попыток отправки на индексацию
links нет, если не указано то будут использоваться ВСЕ непроиндексированные ссылки указанного проекта Переотправляемые ссылки
  • При успешном запросе в ответ будет получен json объект:
{
    "success": true,
    "message": "Links have been successfully added to the project. Invalid links was ignored.",
    "invalid_links": [],
    "project_id": 1,
    "ignored_links": [
        {
            "url": "https://domain.com/url1",
            "attempts": 2
        },
        {
            "url": "https://domain.com/url2",
            "attempts": 2
        }
    ]
}

Где:

Поле Описание
success Статус успешности запроса
message Сообщение об успехе
invalid_links Список невалидных ссылок которые не были добавлены
project_id ID проекта
ignored_links Проигнорированые ссылки, ссылки которые уже отправились max_attempts или более раз

В случае ошибки будет возвращен json объект с сообщениями об ошибках. Например:

{
    "success": false,
    "errors": {
        "max_attempts": [
            "The max attempts field must not be greater than 10."
        ],
        "links": [
            "The links field must be an array."
        ]
    }
}

Или:

{
    "success": false,
    "errors": [
        "You do not have enough tokens to add any links. You need at least 1 tokens."
    ],
    "ignored_links": []
}

Удалить ссылки из проекта

Удаляет ссылки из проекта, для удаления нужно выполнить POST запрос и передать удаляемые ссылки. Если есть дубли ссылок (повторно отправленные или просто дубли) они тоже будут удалены. Можно передать одну ссылку либо массив ссылок. ID проекта нужно передать в адресе эндпоинта

Выполните POST запрос по адресу /api/v1/link/delete/{project_id}

POST https://2index.ninja/api/v1/link/delete/{project_id}

Параметры запроса:

Поле Обязательно Описание
link да Ссылка или массив ссылок для удаления, т.е. может быть как строка так и массив строк
  • При успешном запросе в ответ будет получен json объект:
{
    "success": true,
    "deleted": 12,
    "duplicates": 4,
    "message": "The URLs have been deleted, including duplicate (re-submitted) entries."
}

Где:

Поле Описание
success Статус успешности запроса
message Сообщение об успехе
deleted Список удаленных ссылок
duplicates К-во удаленных дублей ссылок

В случае ошибки будет возвращен json объект с сообщениями об ошибках. Например:

{
    "success": false,
    "errors": {
        "link": [
            "The link field is required."
        ],
    }
}

Работа с источниками ссылок

Источники ссылок доступны для любых типов проектов и обрабатываются одинаково.
Для проектов проверки индексации доступен выбор только google.

Добавление карты сайта

Выполните POST запрос по адресу /api/v1/sitemap/add

POST https://2index.ninja/api/v1/sitemap/add

Параметры запроса:

Поле Обязательно Описание
project_id да ID проекта
sitemap да Ссылка на карту сайта
google нет, при условии yandex или bing Отправлять ссылки в Google
yandex нет, при условии google или bing Отправлять ссылки в Yandex
bing нет, при условии google или yandex Отправлять ссылки в Bing
google_access_granted нет Предоставлен доступ к аккаунту Google
watch нет Следить за изменениями карты сайта

Возможные ошибки:

Ошибка
Ошибка валидации данных. Одно из обязательных полей отсутствует или имеет неверное значение.
Недоступность тарифа. Тарифный план пользователя истек.
Проект не найден. Пользователь не владеет указанным проектом или проект не существует.
Внутренняя ошибка сервера

Примеры ответов:

Успешное добавление карты сайта:

{
    "success": true,
    "message": "Карта сайта успешно добавлена, мы скачаем её как можно скорее и отправим уведомление по электронной почте после завершения."
}

Ошибка валидации:

{
    "errors": ["sitemap":["The sitemap field is required."]]
}

Проект не найден:

{
    "errors": ["Project not found"]
}

Обновление статуса отслеживания карты сайта

Выполните POST запрос по адресу /api/v1/sitemap/update_watch

POST https://2index.ninja/api/v1/sitemap/update_watch

Параметры запроса:

Поле Тип Обязательно Описание
project_id integer да ID проекта
sitemap_id integer да ID карты сайта
watch boolean да Признак того, нужно ли отслеживать изменения карты сайта

Возможные ошибки:

Ошибка
Ошибка валидации данных. Одно из обязательных полей отсутствует или имеет неверное значение.
Проект или источник ссылки не найден. Пользователь не владеет указанным проектом или проект/источник не существует.
Внутренняя ошибка сервера

Примеры ответов:

Успешное обновление статуса отслеживания:

{
    "success": true
}

Источник ссылки не найден:

{
    "errors": ["Link source not found"]
}

Удаление источника ссылок

Выполните POST запрос по адресу /api/v1/sitemap/delete

POST https://2index.ninja/api/v1/sitemap/delete

Параметры запроса:

Поле Тип Обязательно Описание
project_id integer да ID проекта
sitemap_id integer да ID карты сайта

Возможные ошибки:

Ошибка
Ошибка валидации данных. Одно из обязательных полей отсутствует или имеет неверное значение.
Проект или источник ссылки не найден. Пользователь не владеет указанным проектом или проект/источник не существует.
Внутренняя ошибка сервера

Примеры ответов:

Успешное удаление источника ссылок:

{
    "success": true,
    "message": "Источник ссылок успешно удален"
}

Проект не найден:

{
    "errors": ["Project not found"]
}

Список источников ссылок

Для получения списка добавленных источников ссылок нужно сделать POST запрос на https://2index.ninja/api/v1/link_sources

В запросе передать project_id

В результате будет возвращен такой набор данных:

[
    {
        "id": 1247,
        "project_id": 3540,
        "name": "urls.txt",
        "type": "text file",
        "created_at": "2025-01-17T15:51:43.000000Z",
        "processing_date": "2025-01-17T15:51:48.000000Z",
        "has_error": false,
        "error_message": "",
        "status": "success",
        "is_pending": false,
        "is_success": true,
        "total_links": 29585,
        "added_links": 29582,
        "invalid_links": 3,
        "watch": 0,
        "google_access_granted": 0,
        "is_external_links": 1,
        "search_engines": {
            "google": "1"
        }
    },
    {
        "id": 1246,
        "project_id": 3540,
        "name": "urls.txt",
        "type": "text file",
        "created_at": "2025-01-17T15:50:59.000000Z",
        "processing_date": "2025-01-17T15:51:02.000000Z",
        "has_error": false,
        "error_message": "",
        "status": "success",
        "is_pending": false,
        "is_success": true,
        "total_links": 29585,
        "added_links": 10440,
        "invalid_links": 1,
        "watch": 0,
        "google_access_granted": 0,
        "is_external_links": 1,
        "search_engines": {
            "google": "1"
        }
    },
    {
        "id": 1245,
        "project_id": 3540,
        "name": "urls.txt",
        "type": "text file",
        "created_at": "2025-01-17T15:46:17.000000Z",
        "processing_date": null,
        "has_error": false,
        "error_message": null,
        "status": "pending",
        "is_pending": true,
        "is_success": false,
        "total_links": 0,
        "added_links": 0,
        "invalid_links": 0,
        "watch": 0,
        "google_access_granted": 0,
        "is_external_links": 1,
        "search_engines": {
            "google": "1"
        }
    },
    {
        "id": 1244,
        "project_id": 3540,
        "name": "urls.txt",
        "type": "text file",
        "created_at": "2025-01-17T14:52:07.000000Z",
        "processing_date": "2025-01-17T14:53:06.000000Z",
        "has_error": true,
        "error_message": "Unable to encode attribute [invalid_links_list] for model [App\\Models\\LinkSource\\LinkSource] to JSON: Malformed UTF-8 characters, possibly incorrectly encoded.",
        "status": "error",
        "is_pending": false,
        "is_success": false,
        "total_links": 29585,
        "added_links": 0,
        "invalid_links": 3,
        "watch": 0,
        "google_access_granted": 0,
        "is_external_links": 1,
        "search_engines": {
            "google": "1"
        }
    }
]

Где

id - id источника ссылок
project_id - id проекта
name - название прикрепленного файла или адрес карты сайта
type - тип источника файлов (текстовый файл или карта сайта) - может быть: sitemap, text file
created_at - дата слздания
processing_date - дата обработки
has_error - произошла ошибка обработки
error_message - сообщение об ошибке
status - статус - может быть: pending (ожидает обработки), error (ошибка обработки), success
is_pending - сейчас обрабатывается
is_success - успешная обработка
total_links - всего найдено ссылок
added_links - добавлено ссылок
invalid_links - невалидные ссылки
watch - статус наблюдения за картой сайта
google_access_granted - доступ к аккаунту гугл предоставлен или нет
is_external_links - внешние ссылки
search_engines - подключенные поисковые системы

Пример реализации на PHP

<?php

/**
 * Класс для работы с API сервиса 2Index.Ninja
 */
class API_2IndexNinja
{
    /**
     * URL API-эндпоинта
     * @var string
     */
    private $url = 'https://2index.ninja/api/v1/';

    /**
     * Токен доступа к API
     * @var string
     */
    private $access_token;

    /**
     * Конструктор класса.
     *
     * @param string $access_token Токен доступа для авторизации в API.
     */
    public function __construct($access_token)
    {
        $this->access_token = $access_token;
    }

    /*
    |--------------------------------------------------------------------------
    | Методы для работы с аккаунтом
    |--------------------------------------------------------------------------
    */

    /**
     * Получает информацию о текущем аккаунте.
     *
     * @return array|null Декодированный ответ от API с данными аккаунта.
     */
    public function account()
    {
        return $this->make_request('account');
    }

    /*
    |--------------------------------------------------------------------------
    | Методы для работы с проектами
    |--------------------------------------------------------------------------
    */

    /**
     * Получает список всех проектов.
     *
     * @return array|null Декодированный ответ от API со списком проектов.
     */
    public function projects_list()
    {
        return $this->make_request('project');
    }

    /**
     * Получает данные конкретного проекта по его ID.
     *
     * @param int $id ID проекта.
     * @return array|null Декодированный ответ от API с данными проекта.
     */
    public function project($id)
    {
        return $this->make_request('project/' . $id);
    }

    /**
     * Добавляет новый проект для индексации ссылок.
     *
     * @param string $name Название проекта.
     * @param string $website Сайт проекта.
     * @param bool $for_external_links Предназначен ли для внешних ссылок (0 или 1).
     * @param int|null $indexing_speed Скорость индексации.
     * @return array|null Декодированный ответ от API с данными созданного проекта.
     */
    public function add_project($name, $website, $for_external_links = 0, $indexing_speed = null)
    {
        return $this->make_request('project', [
            'name'               => $name,
            'website'            => $website,
            'for_external_links' => $for_external_links,
            'indexing_speed'     => $indexing_speed,
            'type'               => 'indexing',
        ]);
    }

    /**
     * Добавляет новый проект для проверки индексации.
     *
     * @param string $name Название проекта.
     * @param int|null $checking_speed Скорость проверки.
     * @return array|null Декодированный ответ от API с данными созданного проекта.
     */
    public function add_indexing_check_project($name, $checking_speed = null)
    {
        return $this->make_request('project', [
            'name'           => $name,
            'checking_speed' => $checking_speed,
            'type'           => 'indexing_check',
        ]);
    }

    /**
     * Очищает очередь ссылок для проекта.
     *
     * @param int $project_id ID проекта.
     * @return array|null Декодированный ответ от API.
     */
    public function clear_queue($project_id)
    {
        return $this->make_request('project/' . $project_id . '/clear_queue', true);
    }

    /*
    |--------------------------------------------------------------------------
    | Методы для работы со ссылками
    |--------------------------------------------------------------------------
    */

    /**
     * Добавляет ссылки в указанный проект.
     *
     * @param int $project_id ID проекта.
     * @param array|string $links Массив ссылок или одна ссылка в виде строки.
     * @param bool $google Отправлять ли в Google.
     * @param bool $yandex Отправлять ли в Yandex.
     * @param bool $bing Отправлять ли в Bing.
     * @param bool $google_access_granted Флаг, подтверждающий доступ к Google.
     * @return array|null Декодированный ответ от API.
     */
    public function add_links($project_id, $links, $google, $yandex, $bing, $google_access_granted = false)
    {
        return $this->make_request('link/add', [
            'project_id'            => $project_id,
            'links'                 => $links,
            'google'                => $google,
            'yandex'                => $yandex,
            'bing'                  => $bing,
            'google_access_granted' => $google_access_granted,
        ]);
    }

    /**
     * Добавляет ссылки в проект по имени. Если проект не существует, он будет создан.
     *
     * @param array|string $links Массив ссылок или одна ссылка в виде строки.
     * @param bool $google Отправлять ли в Google.
     * @param bool $yandex Отправлять ли в Yandex.
     * @param bool $bing Отправлять ли в Bing.
     * @param string $project_name Имя проекта (по умолчанию 'default').
     * @param bool $google_access_granted Флаг, подтверждающий доступ к Google.
     * @return array|null Декодированный ответ от API.
     */
    public function add_links_simple($links, $google, $yandex, $bing, $project_name = 'default', $google_access_granted = false)
    {
        return $this->make_request('link/add_simple', [
            'project_name'          => $project_name,
            'links'                 => $links,
            'google'                => $google,
            'yandex'                => $yandex,
            'bing'                  => $bing,
            'google_access_granted' => $google_access_granted,
        ]);
    }

    /**
     * Получает источники ссылок для проекта.
     *
     * @param int $project_id ID проекта.
     * @return array|null Декодированный ответ от API.
     */
    public function link_sources($project_id)
    {
        return $this->make_request('link_sources', [
            'project_id' => $project_id
        ]);
    }

    /**
     * Получает статус указанной ссылки
     * Если одна и таже ссылка отправлялась несколько раз выведет статус последней отправленной ссылки
     *
     * @param int $project_id ID проекта
     * @param string $link Проверяемая ссылка
     * @return array Статус ссылки
     */
    public function checkLink($project_id, $link)
    {
        return $this->make_request('link/status', [
            'project_id' => $project_id,
            'link' => $link,
        ]);
    }

    /**
     * Получает статус указанной ссылки
     *
     * @param int $link_id ID ссылки
     * @return array Статус ссылки
     */
    public function checkLinkById($link_id)
    {
        return $this->make_request('link/status/' . $link_id);
    }

    /**
     * Переотправляет непроиндексированные ссылки
     *
     * Если переданы ссылки, которые не отправлялись, они тоже будут добавлены в очередь
     *
     * @param int $project_id ID проекта
     * @param int $max_attempts ограничение максимального к-ва переотправок ссылок (от 1 до 10)
     * @param array $links (не обязательно) массив ссылок для переотправки на индексацию, если ссылки не переданы переотправляет все непроиндексированные ссылки из проекта
     * @return void
     */
    public function resent_notindexed_links($project_id, $max_attempts, array $links = [])
    {
        return $this->make_request('link/resent_notindexed_links/' . $project_id, [
            'max_attempts' => $max_attempts,
            'links' => $links,
        ]);
    }

    /**
     * Удалить ссылку(и) из проекта
     *
     * @param string|array $link
     * @return void
     */
    public function deleteUrls($project_id, $link)
    {
        return $this->make_request('link/delete/' . $project_id, [
            'link' => $link,
        ]);
    }

    /*
    |--------------------------------------------------------------------------
    | Методы для работы с источниками ссылок
    |--------------------------------------------------------------------------
    */

    /**
     * Добавляет Sitemap в проект.
     *
     * @param int $project_id ID проекта.
     * @param string $sitemap_url URL файла Sitemap.
     * @param bool $google Отправлять ли в Google.
     * @param bool $yandex Отправлять ли в Yandex.
     * @param bool $bing Отправлять ли в Bing.
     * @param bool $google_access_granted Флаг, подтверждающий доступ к Google.
     * @param bool $watch Включить ли отслеживание изменений в Sitemap.
     * @return array|null Декодированный ответ от API.
     */
    public function add_sitemap($project_id, $sitemap_url, $google, $yandex, $bing, $google_access_granted = false, $watch = false)
    {
        return $this->make_request('sitemap/add', [
            'project_id'            => $project_id,
            'sitemap'               => $sitemap_url,
            'google'                => $google,
            'yandex'                => $yandex,
            'bing'                  => $bing,
            'google_access_granted' => $google_access_granted,
            'watch'                 => $watch,
        ]);
    }

    /**
     * Включает или отключает отслеживание изменений для Sitemap.
     *
     * @param int $project_id ID проекта.
     * @param int $sitemap_id ID файла Sitemap.
     * @param bool $watch Новый статус отслеживания (true - включить, false - выключить).
     * @return array|null Декодированный ответ от API.
     */
    public function update_sitemap_watch($project_id, $sitemap_id, $watch)
    {
        return $this->make_request('sitemap/update_watch', [
            'project_id' => $project_id,
            'sitemap_id' => $sitemap_id,
            'watch'      => $watch,
        ]);
    }

    /**
     * Удаляет Sitemap из проекта.
     *
     * @param int $project_id ID проекта.
     * @param int $sitemap_id ID файла Sitemap для удаления.
     * @return array|null Декодированный ответ от API.
     */
    public function sitemap_delete($project_id, $sitemap_id)
    {
        return $this->make_request('sitemap/delete', [
            'project_id' => $project_id,
            'sitemap_id' => $sitemap_id,
        ]);
    }

    /**
     * Выполняет запрос к API.
     *
     * @param string $endpoint Эндпоинт API для вызова.
     * @param array|true $post_data Данные для POST-запроса. Если true, отправляется пустой POST.
     * @return array|null Декодированный JSON-ответ от API или null в случае ошибки.
     */
    private function make_request($endpoint, $post_data = [])
    {
        $ch = curl_init($this->url . $endpoint);

        if ($post_data === true) {
            curl_setopt($ch, CURLOPT_POST, 1);
        } elseif ($post_data) {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
        }

        curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer " . $this->access_token]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, false);

        // Указывает user-agent, необходимо указывать, если появляются ошибки 403
        // curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36');

        $result = curl_exec($ch);
        curl_close($ch);

        return json_decode($result, 1);
    }
}