- Chủ yếu
- Tài liệu API
API Documentation
API address
All methods are available at https://2index.ninja/api/v1/.
Authorization
Pass a Bearer access token in the Authorization header with every request. You can obtain the token in the corresponding section of your account. The token does not expire; generating a new token revokes the old one. API access is not included in every plan: if your plan does not include it, the API returns a 401 error.
Accept header
Send the Accept: application/json header with every request. Without it, authorization errors are returned as a 302 redirect to the login page instead of JSON, and 404, 429 and 500 errors are returned as HTML pages.
curl https://2index.ninja/api/v1/account \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json"
Request format
POST parameters can be sent as a form (application/x-www-form-urlencoded or multipart/form-data) or as JSON (with the Content-Type: application/json header). For boolean parameters (google, yandex, bing, watch, etc.) send 1 or 0. The strings "true" and "false" in a form are not recognized by every method.
Response format
Almost every response contains the success field (true or false) that tells whether the request succeeded. On error, the errors field contains the error messages. Depending on the method, errors is:
- an array of strings:
["Project not found"]; - an object "field → list of messages" (validation error):
{"links": ["The links field is required."]}; - in some methods, a different format (a string, an array with an object, etc.); this is noted in the method description.
Validation and business-logic errors are returned with HTTP status 200, so always check success. Error messages are in English.
Response codes
| Code | When it is returned | Response body |
|---|---|---|
200 |
The request was processed, including validation or business-logic errors | {"success": true, ...} or {"success": false, "errors": ...} |
401 |
The token is missing or invalid | {"error": "Unauthenticated."} |
401 |
The user's plan does not include API access | {"success": false, "errors": ["Forbidden"]} |
403 |
The account is banned | {"success": false, "errors": ["Forbidden"]} |
404 |
Unknown method address, or a non-existent project ID in the address (project/{project_id}/clear_queue, link/resent_notindexed_links/{project_id}, link/delete/{project_id}) |
{"message": "..."} |
422 |
Not used: validation errors are returned with status 200 |
— |
429 |
Rate limit exceeded | {"message": "Too Many Attempts."} |
500 |
Internal server error | {"message": "Server Error"} |
Rate limit
No more than 300 requests per minute per user (per IP address for the register method, which is called without a token). When the limit is exceeded, the API returns 429; the Retry-After header contains the number of seconds until the limit resets, and the X-RateLimit-Limit and X-RateLimit-Remaining headers contain the limit and the remaining requests.
403 error and User-Agent
If any request returns 403 without a JSON body {"success": false, ...}, the request was most likely blocked by the hosting protection. In this case, specify a User-Agent, for example:
curl https://2index.ninja/api/v1/account \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
Proxy
Requests from some hosting providers may be restricted at the network level. In this case, we recommend sending requests through a proxy.
Account methods
Register a user
POST https://2index.ninja/api/v1/register
Creates a new account. This method does not require a token. The password is generated automatically.
Request parameters
| Field | Type | Required | Description |
|---|---|---|---|
| string | yes | User email in the format [email protected] |
|
| source | string | no | Registration source, api by default. Can be, for example, wordpress_plugin. |
Request example
curl -X POST https://2index.ninja/api/v1/register \
-H "Accept: application/json" \
-d "[email protected]"
Successful registration response
{
"success": true,
"message": "User registered successfully!",
"account": {
"email": "[email protected]",
"tariff": "White Ninja",
"available_projects": 1,
"balance": null,
"available_links": 0,
"available_indexation_check_links": 0,
"link_sending_speed": 100,
"available_link_sending_speed": 100,
"tariff_available": false,
"tariff_expiring_date": null,
"email_verified": false,
"link_cost": "$0.00056",
"api_key": "15|Xq3vT9kLm2Rp8sWz4yB6nC1dF7gH5jK0aE2uI9oP"
}
}
The api_key field contains the API access token. An email with the password, the token, an email confirmation link and a Telegram account confirmation link will be sent to the specified address.
The free plan is not activated immediately when registering via the API: tokens, limits and the plan expiry date are granted after the email and Telegram are confirmed. Until then, balance is null, tariff_available is false, tariff_expiring_date is null, and you cannot create a project.
Possible errors
Validation error (the email is missing, has an invalid format or is already registered):
{
"success": false,
"errors": {
"email": ["The email has already been taken."]
}
}
Get account data
GET https://2index.ninja/api/v1/account
Request example
curl https://2index.ninja/api/v1/account \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json"
Response
{
"success": true,
"account": {
"email": "[email protected]",
"tariff": "White Ninja",
"available_projects": 1,
"balance": "100.00",
"available_links": 100,
"available_indexation_check_links": 500,
"link_sending_speed": 100,
"available_link_sending_speed": 45,
"tariff_available": true,
"tariff_expiring_date": "2025-01-16T14:26:11.000000Z",
"email_verified": true,
"link_cost": "$0.00056"
}
}
Where
| Field | Description |
|---|---|
email |
User email |
tariff |
Plan name |
available_projects |
How many more projects can be created |
balance |
Token balance (a string with two decimal places) |
available_links |
How many links can be sent for indexing with the current balance |
available_indexation_check_links |
How many links can be sent for indexing check with the current balance |
link_sending_speed |
Daily link sending speed of the plan |
available_link_sending_speed |
Free daily speed not allocated to projects |
tariff_available |
The plan is active and not expired |
tariff_expiring_date |
Plan expiry date (ISO 8601, UTC) or null |
email_verified |
The email is confirmed |
link_cost |
Cost of sending one link on the plan |
Project methods
Get the list of projects
GET https://2index.ninja/api/v1/project
Returns the user's projects, except archived ones, from newest to oldest.
Pagination (optional)
By default (without parameters), all non-archived projects of the user are returned — this keeps backward compatibility.
If the page parameter is passed, the response switches to pagination mode and additionally contains the pagination block.
| Parameter | Type | Required | Description |
|---|---|---|---|
page |
integer | no | Page number. If not passed, all projects are returned. |
per_page |
integer | no | Page size. Taken into account only together with page. Default 20, allowed range 1…100 (out-of-range values are clamped to the nearest bound). |
Request example
curl "https://2index.ninja/api/v1/project?page=2&per_page=10" \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json"
Response
{
"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": 140,
"links_sent_yandex": 0,
"links_sent_bing": 140,
"in_queue": 360,
"sent_links": 140,
"indexed": 90,
"not_indexed": 50,
"instant_indexing": false,
"check_links": true,
"geo_target": {
"criteria_id": 2643,
"name": "Russia"
},
"download_queue_url": "https://2index.ninja/download_project_report/TOKEN/queue",
"download_sent_url": "https://2index.ninja/download_project_report/TOKEN/sent",
"download_indexed_url": "https://2index.ninja/download_project_report/TOKEN/indexed",
"download_unindexed_url": "https://2index.ninja/download_project_report/TOKEN/unindexed"
},
{
"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,
"geo_target": null,
"download_queue_url": "https://2index.ninja/download_project_report/TOKEN/queue",
"download_indexed_url": "https://2index.ninja/download_project_report/TOKEN/indexed",
"download_unindexed_url": "https://2index.ninja/download_project_report/TOKEN/unindexed",
"download_all_url": "https://2index.ninja/download_project_report/TOKEN/all",
"download_checked_url": "https://2index.ninja/download_project_report/TOKEN/checked"
}
]
}
In pagination mode (when page is passed), the response additionally contains the pagination block:
{
"success": true,
"projects": [],
"pagination": {
"current_page": 2,
"last_page": 5,
"per_page": 10,
"total": 47
}
}
The set of project fields depends on the project type. The fields are described in the "Get project data" method.
Get project data
GET https://2index.ninja/api/v1/project/{project_id}
Request example
curl https://2index.ninja/api/v1/project/1 \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json"
Response for an indexing project
{
"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": 140,
"links_sent_yandex": 0,
"links_sent_bing": 140,
"in_queue": 360,
"sent_links": 140,
"indexed": 90,
"not_indexed": 50,
"instant_indexing": false,
"check_links": true,
"geo_target": {
"criteria_id": 2643,
"name": "Russia"
},
"download_queue_url": "https://2index.ninja/download_project_report/TOKEN/queue",
"download_sent_url": "https://2index.ninja/download_project_report/TOKEN/sent",
"download_indexed_url": "https://2index.ninja/download_project_report/TOKEN/indexed",
"download_unindexed_url": "https://2index.ninja/download_project_report/TOKEN/unindexed"
}
}
Response for an indexing check project
{
"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,
"geo_target": {
"criteria_id": 2840,
"name": "United States"
},
"download_queue_url": "https://2index.ninja/download_project_report/TOKEN/queue",
"download_indexed_url": "https://2index.ninja/download_project_report/TOKEN/indexed",
"download_unindexed_url": "https://2index.ninja/download_project_report/TOKEN/unindexed",
"download_all_url": "https://2index.ninja/download_project_report/TOKEN/all",
"download_checked_url": "https://2index.ninja/download_project_report/TOKEN/checked"
}
}
Where
| Field | Description |
|---|---|
id |
Project ID |
name |
Project name |
type |
Project type: indexing — indexing, indexing_check — indexing check |
website |
Website address (indexing only) |
status |
Status: in progress, stopped, completed, wait for moderation, archived |
created_at |
Creation date (Y-m-d H:i:s) |
links_type |
Which links the project accepts: internal, external or internal, external (indexing only) |
google_account_access_granted |
Google account access mark, 0 or 1 (indexing only) |
links_total |
Total links in the project |
links_sending_speed |
Daily sending speed (indexing only) |
links_checking_speed |
Daily checking speed (indexing_check only) |
links_sent_google, links_sent_yandex, links_sent_bing |
Links sent to Google, Yandex, Bing (indexing only) |
in_queue |
Links in the queue |
sent_links |
Total links sent (indexing only) |
checked |
Links checked (indexing_check only) |
indexed |
Indexed |
not_indexed |
Not indexed |
instant_indexing |
Google instant indexing (indexing only) |
check_links |
Automatic indexing check of Google links is enabled (indexing only) |
geo_target |
Google search region for the indexing check: criteria_id and name. null — no region set (the United States is used) |
download_*_url |
Links to download project reports |
Possible errors
The project does not exist or belongs to another user:
{
"success": false,
"errors": ["Project not found"]
}
Create a project
POST https://2index.ninja/api/v1/project
Request parameters
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Project name |
| website | string | yes* | Website address strictly in the format https://site.domain/: http or https scheme, domain and a trailing slash, no path. An address without the trailing slash (https://site.domain) fails validation. *Required if type: indexing is passed. If type is not passed, only the format is checked (when present), so we recommend always passing both type and website |
| type | string | no | Project type: indexing — link indexing, indexing_check — link indexing check. If not specified, a link indexing project indexing is created |
| for_external_links | boolean | no | Project for external links (1). If not specified, the project accepts only internal links (from the website domain). |
| indexing_speed | integer | no** | Daily link sending speed, from 1 to the free speed of the account (available_link_sending_speed). If not specified, the project gets all the free speed of the account. For instant indexing the speed cannot exceed the daily limit of the plan (1 link per day on the free plan); if the speed is not specified, the minimum of the free speed and this limit is used. |
| checking_speed | integer | no** | Daily link checking speed. If not specified, the project gets all the free speed of the account. |
| instant_indexing | boolean | no | Google instant indexing. Available only for indexing projects while the service is enabled; otherwise the API returns an error. Google links are sent with the highest priority and are charged at the instant indexing price of your plan; Yandex and Bing are processed as usual. |
| check_links | boolean | no | Automatic indexing check of Google links for indexing projects. Disabled by default — enabled only with an explicit check_links: 1. ⚠️ When enabled, each Google link costs more: sending + indexing check at your plan's price. Not available for instant indexing projects ( instant_indexing) and ignored for them. |
| geo_target_id | integer | no | Google search region (country) for the indexing check — criteria_id from the regions table or the "Get indexing-check regions" method (for example, 2840 — United States, 2643 — Russia). If not specified — United States. Applies to indexing_check projects and to indexing projects with check_links enabled; ignored otherwise. |
| google_account_access_granted | boolean | no | Mark that you have granted access to your Google account. 0 by default. |
** indexing_speed and checking_speed are aliases and work for a project of any type. If both are passed, indexing_speed is used.
Request examples
Link indexing project:
curl -X POST https://2index.ninja/api/v1/project \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "name=Project 1" \
-d "type=indexing" \
-d "website=https://website.com/" \
-d "for_external_links=1" \
-d "indexing_speed=100"
Instant indexing project:
curl -X POST https://2index.ninja/api/v1/project \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "name=Instant Project" \
-d "type=indexing" \
-d "website=https://website.com/" \
-d "instant_indexing=1" \
-d "indexing_speed=100"
Indexing project with automatic indexing check of Google links (check region — Russia):
curl -X POST https://2index.ninja/api/v1/project \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "name=Project 1" \
-d "type=indexing" \
-d "website=https://website.com/" \
-d "indexing_speed=100" \
-d "check_links=1" \
-d "geo_target_id=2643"
Link indexing check project:
curl -X POST https://2index.ninja/api/v1/project \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "name=Project 2" \
-d "type=indexing_check" \
-d "checking_speed=100" \
-d "geo_target_id=2840"
Response
The project field contains the created project in the same format as in the "Get project data" method:
{
"success": true,
"message": "The project has been successfully created",
"project": {
"id": 3,
"name": "Project 2",
"type": "indexing_check",
"status": "in progress",
"created_at": "2024-03-01 14:34:56",
"links_total": 0,
"links_checking_speed": 100,
"in_queue": 0,
"checked": 0,
"indexed": 0,
"not_indexed": 0,
"geo_target": {
"criteria_id": 2840,
"name": "United States"
},
"download_queue_url": "https://2index.ninja/download_project_report/TOKEN/queue",
"download_indexed_url": "https://2index.ninja/download_project_report/TOKEN/indexed",
"download_unindexed_url": "https://2index.ninja/download_project_report/TOKEN/unindexed",
"download_all_url": "https://2index.ninja/download_project_report/TOKEN/all",
"download_checked_url": "https://2index.ninja/download_project_report/TOKEN/checked"
}
}
Possible errors
Validation error. Note that here errors is an array with a single "field → list of messages" object:
{
"success": false,
"errors": [
{
"website": ["The website field must be a valid URL. For example https://site.domain/"]
}
]
}
Other errors are returned as an array of strings, for example:
{
"success": false,
"errors": ["The limit of available projects has been reached"]
}
| Error | Reason |
|---|---|
You must confirm your email |
The email is not confirmed |
The limit of available projects has been reached |
The plan's project limit has been reached |
You cannot create the project. Your tariff has expired |
The plan is inactive or expired |
You must confirm your telegram account |
The Telegram account is not confirmed on the free plan |
Unable to create the project. Your daily sending speed is fully allocated to other projects. ... |
No speed was specified, and all the account speed is already allocated to other projects |
Instant indexing is available only for indexing projects. |
instant_indexing was passed for an indexing_check project (in the validation object) |
Instant indexing is currently unavailable. |
The instant indexing service is currently disabled (in the validation object) |
Your tariff limits instant indexing speed to N per day. |
The instant indexing speed exceeds the plan limit (in the validation object) |
Get indexing-check regions
GET https://2index.ninja/api/v1/geo-targets
Returns the list of Google search regions (countries), sorted by name. Pass criteria_id in the geo_target_id parameter when creating a project. A regular page with the regions table is available at https://2index.ninja/en/geo-targets.
Request example
curl https://2index.ninja/api/v1/geo-targets \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json"
Response
{
"success": true,
"geo_targets": [
{
"criteria_id": 2643,
"name": "Russia",
"country_code": "ru"
},
{
"criteria_id": 2840,
"name": "United States",
"country_code": "us"
}
]
}
Create (or get) a project for the WordPress plugin
POST https://2index.ninja/api/v1/account/get_wordpress_project
Finds the indexing project linked to a WordPress website. If there is no such project, creates a new one.
Request parameters
| Field | Type | Required | Description |
|---|---|---|---|
| website | string | yes | Website address. It is normalized to https://site.domain/: the scheme defaults to https, the domain is lowercased, and the path is dropped. For example, Site.domain/blog becomes https://site.domain/. |
The method looks for a non-archived user project for internal links with the same website address. If none is found, it creates an indexing project for internal links named after the domain, with all the free sending speed of the account.
Request example
curl -X POST https://2index.ninja/api/v1/account/get_wordpress_project \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "website=https://domain.com/"
Response for an existing project
{
"success": true,
"message": "Found existing project domain.com",
"project": {
"id": 1,
"name": "domain.com",
"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": 140,
"links_sent_yandex": 0,
"links_sent_bing": 140,
"in_queue": 360,
"sent_links": 140,
"indexed": 90,
"not_indexed": 50,
"instant_indexing": false,
"check_links": false,
"geo_target": null,
"download_queue_url": "https://2index.ninja/download_project_report/TOKEN/queue",
"download_sent_url": "https://2index.ninja/download_project_report/TOKEN/sent",
"download_indexed_url": "https://2index.ninja/download_project_report/TOKEN/indexed",
"download_unindexed_url": "https://2index.ninja/download_project_report/TOKEN/unindexed"
}
}
Response for a new project
{
"success": true,
"message": "The project has been successfully created",
"project": {
"id": 4,
"name": "domain.com",
"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": 0,
"links_sending_speed": 45,
"links_sent_google": 0,
"links_sent_yandex": 0,
"links_sent_bing": 0,
"in_queue": 0,
"sent_links": 0,
"indexed": 0,
"not_indexed": 0,
"instant_indexing": false,
"check_links": false,
"geo_target": null,
"download_queue_url": "https://2index.ninja/download_project_report/TOKEN/queue",
"download_sent_url": "https://2index.ninja/download_project_report/TOKEN/sent",
"download_indexed_url": "https://2index.ninja/download_project_report/TOKEN/indexed",
"download_unindexed_url": "https://2index.ninja/download_project_report/TOKEN/unindexed"
}
}
Possible errors
A validation error is returned without the success and errors fields, as a "field → list of messages" object:
{
"website": ["The website field must be a valid URL. For example https://site.domain/"]
}
When a new project is created, the same errors as in the "Create a project" method are possible (You must confirm your email, The limit of available projects has been reached, etc.).
Clear the indexing queue
POST https://2index.ninja/api/v1/project/{project_id}/clear_queue
Removes links that have not been sent yet (queued) from the project. Tokens for the removed links are returned to the balance. Works for projects of both types.
Request example
curl -X POST https://2index.ninja/api/v1/project/1/clear_queue \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json"
Response
{
"success": true,
"message": "The indexing queue has been cleared successfully. 360 links have been removed"
}
Possible errors
The project belongs to another user:
{
"success": false,
"errors": ["Project not found"]
}
The project is deeply archived:
{
"success": false,
"errors": ["You cannot clear queue. The project is deeply archived"]
}
If there is no project with this ID, HTTP status 404 is returned.
Reset speed of completed projects
POST https://2index.ninja/api/v1/project/reset_speed_completed
A bulk operation — sets the speed to 0 for all completed (completed) projects of the user. Useful when, after many projects are completed, you need to free up the allocated speed without archiving them.
Request parameters
Without parameters, all completed projects of the user with a speed greater than 0 are affected. All filter parameters are optional; dates are passed in the Y-m-d format, range bounds are inclusive.
| Field | Type | Required | Description |
|---|---|---|---|
created_at_from |
string | no | Project creation date, lower bound (Y-m-d). |
created_at_to |
string | no | Project creation date, upper bound (Y-m-d). |
completed_at_from |
string | no | Date of transition to completed, lower bound. |
completed_at_to |
string | no | Date of transition to completed, upper bound. |
Request example
curl -X POST https://2index.ninja/api/v1/project/reset_speed_completed \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "completed_at_from=2025-01-01" \
-d "completed_at_to=2025-01-31"
Response
{
"success": true,
"message": "Speed reset for 5 projects",
"affected_projects": 5
}
Possible errors
Invalid date format. Here errors is an array with a single "field → list of messages" object:
{
"success": false,
"errors": [
{
"completed_at_from": ["The completed at from field must match the format Y-m-d."]
}
]
}
Archive completed projects
POST https://2index.ninja/api/v1/project/archive_completed
A bulk operation — moves all completed (completed) projects of the user to the archived status and resets their speed. Useful for closing completed projects in bulk without per-project requests.
Request parameters
Accepts the same optional date range filters as "Reset speed of completed projects":
| Field | Type | Required | Description |
|---|---|---|---|
created_at_from |
string | no | Project creation date, lower bound (Y-m-d). |
created_at_to |
string | no | Project creation date, upper bound (Y-m-d). |
completed_at_from |
string | no | Date of transition to completed, lower bound. |
completed_at_to |
string | no | Date of transition to completed, upper bound. |
Request example
curl -X POST https://2index.ninja/api/v1/project/archive_completed \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json"
Response
{
"success": true,
"message": "5 projects have been archived",
"archived_count": 5
}
Possible errors
Invalid date format — in the same format as in the "Reset speed of completed projects" method.
Link methods
Add links
POST https://2index.ninja/api/v1/link/add
Adds links to an existing project. For indexing check projects, links are added the same way as for indexing, but the check is currently available only in Google — pass only google=1.
Request parameters
| Field | Required | Description |
|---|---|---|
| project_id | yes | Project ID |
| links | yes | List of links: an array (links[]=...) or text with each link on a new line. Surrounding spaces and duplicates are removed |
| no, if yandex or bing is specified | Send links to Google (1 or 0) |
|
| yandex | no, if google or bing is specified | Send links to Yandex (1 or 0) |
| bing | no, if google or yandex is specified | Send links to Bing (1 or 0) |
At least one of the google, yandex, bing parameters must be 1. The google_access_granted parameter mentioned in previous versions of the documentation is not used by this method.
How links are processed
- Strings that are not valid URLs (
http://orhttps://, no spaces, etc.) are not added and do not cause an error: they are returned in theinvalid_linksfield of the successful response. - If some valid URLs are longer than 3000 characters or are not from the project domain (for an internal-links-only project, or if your plan does not allow external links), no links are added and an error is returned.
- If the token balance is not enough for all the links, the first links of the list that the balance covers are added; the response is still successful.
Request example
curl -X POST https://2index.ninja/api/v1/link/add \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "project_id=1" \
-d "links[]=https://domain.com/page1" \
-d "links[]=https://domain.com/page2" \
-d "google=1" \
-d "bing=1"
Response
The message of a successful response always contains the phrase Invalid links was ignored., and the invalid_links field is always present — an empty array if there were no invalid links:
{
"success": true,
"message": "Links have been successfully added to the project. Invalid links was ignored.",
"invalid_links": ["not a link"],
"project_id": 1
}
Possible errors
The links contain external or too long links. The error text contains <br> HTML tags:
{
"success": false,
"errors": ["You sent invalid links. <br> You can only add internal links to this project<br><br>Invalid links:<br>https://other-site.com/page"],
"invalid_links": ["https://other-site.com/page"]
}
Validation error (errors is a "field → list of messages" object):
{
"success": false,
"errors": {
"google": ["At least one of Google, Yandex, or Bing must be selected."]
}
}
Other errors are returned as an array of strings:
| Error | Reason |
|---|---|
Project not found |
project_id is missing, the project does not exist or belongs to another user |
You cannot add links to the project. The project is deeply archived |
The project is deeply archived |
You cannot add links to the project. Your tariff has expired. |
The plan is inactive or expired |
You do not have enough tokens to add any links. You need at least N tokens. |
The balance is not enough for a single link |
To check indexing, you can only select Google. |
Not only Google was selected for an indexing check project (in the validation object) |
Adding links to Yandex is temporarily unavailable. |
Adding links to this search engine is temporarily disabled (in the validation object) |
An error occurred while adding links: ... |
The links could not be added, for example: Instant indexing is temporarily unavailable. You cannot add links to this project. |
Add links by project name
POST https://2index.ninja/api/v1/link/add_simple
Adds links to a project found by name. The method looks for a user project with the in progress, stopped or completed status. If there is no such project, an indexing project without a website address is created automatically, for internal and external links, with all the free sending speed of the account.
Request parameters
| Field | Required | Description |
|---|---|---|
| project_name | no | Project name. If not specified, the project named default is used. |
| links | yes | List of links: an array or text with each link on a new line. |
| no, if yandex or bing is specified | Send links to Google (1 or 0). |
|
| yandex | no, if google or bing is specified | Send links to Yandex (1 or 0). |
| bing | no, if google or yandex is specified | Send links to Bing (1 or 0). |
At least one of the google, yandex, bing parameters must be 1. If the found project is an indexing check project, pass only google=1. Links are processed the same way as in the "Add links" method.
Request example
curl -X POST https://2index.ninja/api/v1/link/add_simple \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"project_name": "My Website",
"links": ["https://example.com/page1", "https://example.com/page2"],
"google": 1,
"yandex": 0,
"bing": 1
}'
Response
{
"success": true,
"message": "Links have been successfully added to the project. Invalid links was ignored.",
"invalid_links": [],
"project_id": 12345
}
Possible errors
Link processing and balance errors are the same as in the "Add links" method. A validation error is returned as a "field → list of messages" object:
{
"success": false,
"errors": {
"links": ["The links field is required."]
}
}
Errors when creating a new project (an array of strings):
| Error | Reason |
|---|---|
Unable to create a new project. The limit of available projects has been reached. Please specify the name of an existing project. |
The plan's project limit has been reached |
You must confirm your email |
The email is not confirmed |
You cannot create the project. Your tariff has expired |
The plan is inactive or expired |
You must confirm your telegram account |
The Telegram account is not confirmed on the free plan |
Unable to create a new project. Your daily sending speed is fully allocated to other projects. ... |
All the account speed is already allocated to other projects |
If the project is found but the plan is inactive: You cannot add links to the project. Your tariff has expired.
Check link status
POST https://2index.ninja/api/v1/link/status
Returns the status of a link in an indexing project. If the link was added several times, the latest record is returned. For indexing check projects, the method always returns URL not found.
Request parameters
| Field | Required | Description |
|---|---|---|
| project_id | yes | Project ID |
| link | yes | The link to check (exact match) |
Request example
curl -X POST https://2index.ninja/api/v1/link/status \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "project_id=1" \
-d "link=https://2index.ninja/"
Response
{
"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_sent_attempts": 1,
"yandex_sent_attempts": 1,
"bing_sent_attempts": 1,
"google_indexed": 1,
"google_indexing_check_date": "2025-08-29"
}
}
Where
| Field | Description |
|---|---|
id |
Link ID |
url |
Link |
google |
* Google sending status |
yandex |
* Yandex sending status |
bing |
* Bing sending status |
is_external |
External link (0 or 1) |
google_sent |
Date sent to Google |
yandex_sent |
Date sent to Yandex |
bing_sent |
Date sent to Bing |
google_sent_attempts |
Number of submissions to Google |
yandex_sent_attempts |
Number of submissions to Yandex |
bing_sent_attempts |
Number of submissions to Bing |
google_indexed |
Indexed in Google (0 or 1) |
google_indexing_check_date |
Google indexing check date |
* Possible statuses
| Status | Meaning |
|---|---|
New |
New |
Sent |
Sent |
In the queue |
In the sending queue |
In the process |
Being sent |
Error sending |
An error occurred while sending |
Don't index |
Not sent to this search engine |
Sent to reindexing |
Sent for reindexing |
Possible errors
{
"success": false,
"errors": {
"link": ["The link field is required."]
}
}
{
"success": false,
"errors": ["Project not found"]
}
{
"success": false,
"errors": ["URL not found"]
}
Get link status by ID
GET https://2index.ninja/api/v1/link/status/{link_id}
Returns the status of a link by its ID (the id field from the "Check link status" method). Works only for links of indexing projects.
Request example
curl https://2index.ninja/api/v1/link/status/34368960 \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json"
Response
The same as in the "Check link status" method.
Possible errors
No link with this ID — {"success": false, "errors": ["URL not found"]}; the link belongs to another user's project — {"success": false, "errors": ["Project not found"]}.
Resend links for reindexing
POST https://2index.ninja/api/v1/link/resent_notindexed_links/{project_id}
Resends non-indexed links of an indexing project to Google. The project ID is passed in the address.
If links is not passed, the method takes all project links that were sent to Google, checked for indexing, not indexed, and sent fewer than max_attempts times. If links is passed, the listed links sent fewer than max_attempts times are resent; links that have never been sent are added to the queue too. Links are added according to the balance, as in the "Add links" method, and the previous records of these links get the Sent to reindexing status.
Request parameters
| Field | Required | Description |
|---|---|---|
| max_attempts | yes | Limit of link submissions, an integer from 1 to 10. Links sent max_attempts times or more are skipped |
| links | no | Array of links to resend. If not specified, all suitable non-indexed links of the project are used |
Request example
curl -X POST https://2index.ninja/api/v1/link/resent_notindexed_links/1 \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "max_attempts=3"
Response
{
"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": 3
},
{
"url": "https://domain.com/url2",
"attempts": 4
}
]
}
Where
| Field | Description |
|---|---|
success |
Request success status |
message |
Success message |
invalid_links |
Invalid links that were not added |
project_id |
Project ID |
ignored_links |
Skipped links that were already sent max_attempts times or more, with the number of submissions |
Possible errors
Validation error:
{
"success": false,
"errors": {
"max_attempts": ["The max attempts field must not be greater than 10."],
"links": ["The links field must be an array."]
}
}
No links to resend. Note that the text is returned in the message field, not in errors:
{
"success": false,
"message": "No links available for reindexing"
}
Not enough tokens (the ignored_links field is present in the error response too):
{
"success": false,
"errors": ["You do not have enough tokens to add any links. You need at least 1 tokens."],
"ignored_links": []
}
The project belongs to another user. Here errors is a string:
{
"success": false,
"errors": "Project not found"
}
The project is deeply archived — {"success": false, "errors": ["You cannot work with links. The project is deeply archived"]}. If there is no project with this ID, HTTP status 404 is returned.
Delete links from a project
POST https://2index.ninja/api/v1/link/delete/{project_id}
Deletes a link or an array of links from a project (all records with this address). The project ID is passed in the address. If a link is still in the sending queue, its tokens are returned to the balance. Links that have already been sent are deleted without a refund.
Request parameters
| Field | Required | Description |
|---|---|---|
| link | yes | The link to delete: a single string or an array of links (link[]=...). |
Request example
curl -X POST https://2index.ninja/api/v1/link/delete/1 \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "link[]=https://domain.com/page1" \
-d "link[]=https://domain.com/page2"
Response
{
"success": true,
"deleted": 2,
"message": "The URLs have been deleted."
}
If the project contained several identical URLs (for example, a link was re-submitted), the response has an additional duplicates field:
{
"success": true,
"deleted": 5,
"duplicates": 3,
"message": "The URLs have been deleted, including duplicate (re-submitted) entries."
}
If none of the passed links were found in the project:
{
"success": true,
"deleted": 0,
"message": "No URLs were found to delete."
}
Possible errors
{
"success": false,
"errors": {
"link": ["The link field is required."]
}
}
{
"success": false,
"errors": ["You cannot work with links. The project is deeply archived"]
}
The project belongs to another user. Here errors is a string:
{
"success": false,
"errors": "Project not found"
}
If there is no project with this ID, HTTP status 404 is returned.
Link source methods
Link sources are sitemaps and text files from which links are loaded into a project. They are available for projects of any type and are processed the same way. For indexing check projects, the check is performed only in Google, so pass only google=1.
In all methods of this section, errors are returned in the {"success": false, "errors": ["..."]} format. Common errors:
| Error | Reason |
|---|---|
Project not found |
project_id is missing, the project does not exist or belongs to another user |
You cannot work with the link source. The project is deeply archived |
The project is deeply archived |
Add a sitemap
POST https://2index.ninja/api/v1/sitemap/add
Adds a sitemap to a project. The sitemap is downloaded in the background; you will receive an email notification when it is processed. The processing state is available via the "Get the list of link sources" method.
Request parameters
| Field | Required | Description |
|---|---|---|
| project_id | yes | Project ID |
| sitemap | yes | Sitemap URL |
| no, if yandex or bing is specified | Send links to Google (1 or 0) |
|
| yandex | no, if google or bing is specified | Send links to Yandex (1 or 0) |
| bing | no, if google or yandex is specified | Send links to Bing (1 or 0) |
| is_external | no | Links from the sitemap are external (1). 0 by default |
| google_access_granted | no | Google account access mark (1 or 0) |
| watch | no | Watch the sitemap for changes (1 or 0). 0 by default |
Request example
curl -X POST https://2index.ninja/api/v1/sitemap/add \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "project_id=1" \
-d "sitemap=https://domain.com/sitemap.xml" \
-d "google=1" \
-d "watch=1"
Response
The sitemap field contains the created link source in the format of the "Get the list of link sources" method:
{
"success": true,
"message": "The sitemap has been successfully added, we will download it as quickly as possible, and upon completion we will send an email.",
"sitemap": {
"id": 1248,
"project_id": 1,
"name": "https://domain.com/sitemap.xml",
"type": "sitemap",
"created_at": "2025-01-17T16:02:11.000000Z",
"processing_date": null,
"has_error": false,
"error_message": null,
"status": "pending",
"is_pending": true,
"is_success": false,
"total_links": null,
"added_links": null,
"invalid_links": null,
"watch": true,
"google_access_granted": false,
"is_external_links": false,
"search_engines": {
"google": 1
}
}
}
Possible errors
Validation error. Note that the error object is returned as a JSON string inside the errors array:
{
"success": false,
"errors": ["{\"sitemap\":[\"The sitemap field is required.\"]}"]
}
The plan is inactive or expired:
{
"success": false,
"errors": ["You cannot add links to the project. Your tariff has expired."]
}
If adding links to the selected search engine is temporarily disabled, the validation string contains a message like Adding links to Yandex is temporarily unavailable.
Update sitemap watching
POST https://2index.ninja/api/v1/sitemap/update_watch
Enables or disables watching a sitemap for changes.
Request parameters
| Field | Type | Required | Description |
|---|---|---|---|
| project_id | integer | yes | Project ID |
| sitemap_id | integer | yes | Sitemap ID (the id field of the link source) |
| watch | boolean | no | 1 — watch for changes, 0 — do not watch. If the parameter is not passed, watching is disabled |
Request example
curl -X POST https://2index.ninja/api/v1/sitemap/update_watch \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "project_id=1" \
-d "sitemap_id=1248" \
-d "watch=0"
Response
{
"success": true
}
Possible errors
No source with this ID in the project:
{
"success": false,
"errors": ["Sitemap not found"]
}
The link source is not a sitemap (for example, a text file):
{
"success": false,
"errors": ["Wrong link source type"]
}
Delete a link source
POST https://2index.ninja/api/v1/sitemap/delete
Deletes a link source from a project — a sitemap or a text file.
Request parameters
| Field | Type | Required | Description |
|---|---|---|---|
| project_id | integer | yes | Project ID |
| sitemap_id | integer | yes | Link source ID (the id field from the "Get the list of link sources" method) |
Request example
curl -X POST https://2index.ninja/api/v1/sitemap/delete \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "project_id=1" \
-d "sitemap_id=1248"
Response
The message is the same for sitemaps and text files:
{
"success": true,
"message": "The sitemap has been successfully deleted"
}
Possible errors
No source with this ID in the project:
{
"success": false,
"errors": ["Sitemap not found"]
}
Get the list of link sources
POST https://2index.ninja/api/v1/link_sources
Returns the link sources of a project (sitemaps and text files), from newest to oldest.
Request parameters
| Field | Type | Required | Description |
|---|---|---|---|
| project_id | integer | yes | Project ID |
Request example
curl -X POST https://2index.ninja/api/v1/link_sources \
-H "Authorization: Bearer API_TOKEN" \
-H "Accept: application/json" \
-d "project_id=3540"
Response
On success, an array of sources is returned without the success field:
[
{
"id": 1247,
"project_id": 3540,
"name": "https://domain.com/sitemap.xml",
"type": "sitemap",
"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": 1,
"google_access_granted": 0,
"is_external_links": 0,
"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",
"bing": "1"
}
}
]
Where
| Field | Description |
|---|---|
id |
Link source ID |
project_id |
Project ID |
name |
Sitemap address or uploaded file name |
type |
Source type: sitemap or text file |
created_at |
Creation date (ISO 8601, UTC) |
processing_date |
Processing date or null |
has_error |
A processing error occurred |
error_message |
Error message |
status |
Status: pending (waiting for processing), error (processing error), success (processed) |
is_pending |
Waiting for processing |
is_success |
Processed successfully |
total_links |
Total links found |
added_links |
Links added |
invalid_links |
Number of invalid links |
watch |
Watching the sitemap for changes (0 or 1) |
google_access_granted |
Google account access mark (0 or 1) |
is_external_links |
Links are marked as external (0 or 1) |
search_engines |
Selected search engines |
Possible errors
{
"success": false,
"errors": ["Project not found"]
}
PHP implementation example
<?php
/**
* Class for working with the 2Index.Ninja API
*/
class API_2IndexNinja
{
/**
* API endpoint URL
* @var string
*/
private $url = 'https://2index.ninja/api/v1/';
/**
* API access token
* @var string
*/
private $access_token;
/**
* Class constructor.
*
* @param string $access_token Access token for API authorization.
*/
public function __construct($access_token)
{
$this->access_token = $access_token;
}
/*
|--------------------------------------------------------------------------
| Account methods
|--------------------------------------------------------------------------
*/
/**
* Gets information about the current account.
*
* @return array|null Decoded API response with account data.
*/
public function account()
{
return $this->make_request('account');
}
/**
* Registers a new user. This method does not require a token.
*
* @param string $email New user's email.
* @param string $source Registration source.
* @return array|null Decoded API response (the token is in account.api_key).
*/
public function register_user($email, $source = 'api')
{
return $this->make_request('register', [
'email' => $email,
'source' => $source,
]);
}
/*
|--------------------------------------------------------------------------
| Project methods
|--------------------------------------------------------------------------
*/
/**
* Gets the list of the user's projects.
*
* Without parameters, returns all non-archived projects. If $page is passed,
* pagination is enabled and the response contains the 'pagination' block.
*
* @param int|null $page Page number (if specified, pagination is enabled).
* @param int|null $per_page Page size (1..100, 20 by default). Used only with $page.
* @return array|null Decoded API response with the list of projects.
*/
public function projects_list($page = null, $per_page = null)
{
$url_data = [];
if ($page) {
$url_data['page'] = $page;
if ($per_page) {
$url_data['per_page'] = $per_page;
}
}
$url_data = $url_data ? ('?' . http_build_query($url_data)) : '';
return $this->make_request('project' . $url_data);
}
/**
* Gets the data of a specific project by its ID.
*
* @param int $id Project ID.
* @return array|null Decoded API response with the project data.
*/
public function project($id)
{
return $this->make_request('project/' . $id);
}
/**
* Adds a new link indexing project.
*
* @param string $name Project name.
* @param string $website Project website in the format https://site.domain/ (with a trailing slash).
* @param bool $for_external_links Whether the project is for external links (0 or 1).
* @param int|null $indexing_speed Indexing speed.
* @return array|null Decoded API response with the created project data.
*/
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',
]);
}
/**
* Adds a new indexing check project.
*
* @param string $name Project name.
* @param int|null $checking_speed Checking speed.
* @param int|null $geo_target_id Google search region (criteria_id from geo_targets()).
* @return array|null Decoded API response with the created project data.
*/
public function add_indexing_check_project($name, $checking_speed = null, $geo_target_id = null)
{
return $this->make_request('project', [
'name' => $name,
'checking_speed' => $checking_speed,
'geo_target_id' => $geo_target_id,
'type' => 'indexing_check',
]);
}
/**
* Gets the list of Google search regions for the indexing check.
*
* @return array|null Decoded API response.
*/
public function geo_targets()
{
return $this->make_request('geo-targets');
}
/**
* Finds the project linked to a WordPress website.
* If there is no such project, creates a new one.
*
* @param string $website Website URL to look up the project by.
* @return array|null Decoded API response with the project data.
*/
public function get_wordpress_project($website)
{
return $this->make_request('account/get_wordpress_project', ['website' => $website]);
}
/**
* Clears the link queue of a project.
*
* @param int $project_id Project ID.
* @return array|null Decoded API response.
*/
public function clear_queue($project_id)
{
return $this->make_request('project/' . $project_id . '/clear_queue', true);
}
/**
* Resets the indexing speed of all completed projects of the user.
* All filter parameters are optional; dates in the Y-m-d format.
*
* @param string|null $created_at_from
* @param string|null $created_at_to
* @param string|null $completed_at_from
* @param string|null $completed_at_to
* @return array|null Decoded response: success, message, affected_projects.
*/
public function reset_speed_completed(
$created_at_from = null,
$created_at_to = null,
$completed_at_from = null,
$completed_at_to = null
) {
$payload = array_filter([
'created_at_from' => $created_at_from,
'created_at_to' => $created_at_to,
'completed_at_from' => $completed_at_from,
'completed_at_to' => $completed_at_to,
]);
// Without parameters, make_request() treats an empty array as "no POST
// data" and sends a GET, which is caught by the project/{id} route.
// So with empty filters we force a POST by passing true.
return $this->make_request('project/reset_speed_completed', $payload ?: true);
}
/**
* Archives all completed projects of the user.
* Accepts the same optional date range filters as reset_speed_completed.
*
* @param string|null $created_at_from
* @param string|null $created_at_to
* @param string|null $completed_at_from
* @param string|null $completed_at_to
* @return array|null Decoded response: success, message, archived_count.
*/
public function archive_completed(
$created_at_from = null,
$created_at_to = null,
$completed_at_from = null,
$completed_at_to = null
) {
$payload = array_filter([
'created_at_from' => $created_at_from,
'created_at_to' => $created_at_to,
'completed_at_from' => $completed_at_from,
'completed_at_to' => $completed_at_to,
]);
return $this->make_request('project/archive_completed', $payload ?: true);
}
/*
|--------------------------------------------------------------------------
| Link methods
|--------------------------------------------------------------------------
*/
/**
* Adds links to the specified project.
*
* @param int $project_id Project ID.
* @param array|string $links Array of links or text (each link on a new line).
* @param bool $google Whether to send to Google.
* @param bool $yandex Whether to send to Yandex.
* @param bool $bing Whether to send to Bing.
* @return array|null Decoded API response.
*/
public function add_links($project_id, $links, $google, $yandex, $bing)
{
return $this->make_request('link/add', [
'project_id' => $project_id,
'links' => $links,
'google' => (int) $google,
'yandex' => (int) $yandex,
'bing' => (int) $bing,
]);
}
/**
* Adds links to a project by name. If the project does not exist, it is created.
*
* @param array|string $links Array of links or text (each link on a new line).
* @param bool $google Whether to send to Google.
* @param bool $yandex Whether to send to Yandex.
* @param bool $bing Whether to send to Bing.
* @param string $project_name Project name ('default' by default).
* @return array|null Decoded API response.
*/
public function add_links_simple($links, $google, $yandex, $bing, $project_name = 'default')
{
return $this->make_request('link/add_simple', [
'project_name' => $project_name,
'links' => $links,
'google' => (int) $google,
'yandex' => (int) $yandex,
'bing' => (int) $bing,
]);
}
/**
* Gets the status of the specified link.
* If the same link was sent several times, returns the status of the latest record.
*
* @param int $project_id Project ID
* @param string $link The link to check
* @return array|null Link status
*/
public function checkLink($project_id, $link)
{
return $this->make_request('link/status', [
'project_id' => $project_id,
'link' => $link,
]);
}
/**
* Gets the status of a link by its ID.
*
* @param int $link_id Link ID
* @return array|null Link status
*/
public function checkLinkById($link_id)
{
return $this->make_request('link/status/' . $link_id);
}
/**
* Resends non-indexed links of a project for indexing.
* If $links is not passed, all non-indexed project links
* sent fewer than $max_attempts times are used.
*
* @param int $project_id Project ID.
* @param int $max_attempts Maximum number of submissions (1..10).
* @param array|null $links Specific list of links to resend.
* @return array|null
*/
public function resent_notindexed_links($project_id, $max_attempts, $links = null)
{
return $this->make_request('link/resent_notindexed_links/' . $project_id, [
'max_attempts' => $max_attempts,
'links' => $links,
]);
}
/**
* Deletes a link or an array of links from a project.
*
* @param int $project_id Project ID.
* @param string|array $link The link to delete (or an array).
* @return array|null
*/
public function deleteUrls($project_id, $link)
{
return $this->make_request('link/delete/' . $project_id, [
'link' => $link,
]);
}
/*
|--------------------------------------------------------------------------
| Link source methods
|--------------------------------------------------------------------------
*/
/**
* Adds a sitemap to a project.
*
* @param int $project_id Project ID.
* @param string $sitemap_url Sitemap URL.
* @param bool $google Whether to send to Google.
* @param bool $yandex Whether to send to Yandex.
* @param bool $bing Whether to send to Bing.
* @param bool $google_access_granted Google account access mark.
* @param bool $watch Whether to watch the sitemap for changes.
* @param bool $is_external Whether to mark links from the sitemap as external.
* @return array|null Decoded API response.
*/
public function add_sitemap($project_id, $sitemap_url, $google, $yandex, $bing, $google_access_granted = false, $watch = false, $is_external = false)
{
return $this->make_request('sitemap/add', [
'project_id' => $project_id,
'sitemap' => $sitemap_url,
'google' => (int) $google,
'yandex' => (int) $yandex,
'bing' => (int) $bing,
'google_access_granted' => (int) $google_access_granted,
'watch' => (int) $watch,
'is_external' => (int) $is_external,
]);
}
/**
* Enables or disables watching a sitemap for changes.
*
* @param int $project_id Project ID.
* @param int $sitemap_id Sitemap ID.
* @param bool $watch New watching status (true - enable, false - disable).
* @return array|null Decoded API response.
*/
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' => (int) $watch,
]);
}
/**
* Deletes a link source (a sitemap or a text file) from a project.
*
* @param int $project_id Project ID.
* @param int $sitemap_id Link source ID.
* @return array|null Decoded API response.
*/
public function sitemap_delete($project_id, $sitemap_id)
{
return $this->make_request('sitemap/delete', [
'project_id' => $project_id,
'sitemap_id' => $sitemap_id,
]);
}
/**
* Gets the link sources of a project.
* On success, returns an array of sources without the success field.
*
* @param int $project_id Project ID.
* @return array|null Decoded API response.
*/
public function link_sources($project_id)
{
return $this->make_request('link_sources', [
'project_id' => $project_id,
]);
}
/**
* Sends a request to the API.
*
* @param string $endpoint API endpoint to call.
* @param array|true $post_data POST data. If true, an empty POST is sent.
* An empty array means a GET request.
* @return array|null Decoded JSON response or null on error.
*/
private function make_request($endpoint, $post_data = [])
{
$ch = curl_init($this->url . $endpoint);
if ($post_data === true) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, '');
} 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,
// Without this header, authorization, 404 and 429 errors are not returned as JSON
'Accept: application/json',
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
// Sets the user agent; specify it if you get 403 errors
// 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);
if ($result === false) {
return null;
}
return json_decode($result, true);
}
}