Semalt for developers

Public API v1

Read and manage account websites, analytics organization, campaign keywords, and indexing through a stable, AI-friendly HTTP API.

Developer access

Get your Semalt API key

Create a free Semalt account to access the Public API and connect AI tools through MCP.

Loading API access...

Quick start

One API key can read and manage the accounts available to it. Start with /me to identify the token owner’s account_id, then use /accounts to discover account contexts available for selection. Authenticate every request with the Authorization: Bearer header.

curl 'https://semalt.com/api/v1/me' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json'

Alternatively, pass the API key as the token query parameter. Header authentication is recommended because URLs can be recorded in logs and browser history.

curl 'https://semalt.com/api/v1/me?token=YOUR_API_KEY' \
  -H 'Accept: application/json'
Base URLhttps://semalt.com/api/v1
For POST requests Send the body as JSON

Choose an account from /accounts and replace 20 in the example with its account_id. Every write endpoint accepts one JSON object and requires Content-Type: application/json. Endpoints that do not need fields still expect an empty JSON object: {}.

curl --request POST \
  --url 'https://semalt.com/api/v1/accounts/20/sites' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{"domain":"example.com"}'

Choose an account context with one key

Your API key identifies the token owner. The account_id in each account endpoint selects the account context for that request. Use /accounts to discover account contexts available for selection; the same key works for reads and writes.

  1. Call GET /me. Its data.account_id always identifies the API key owner.
  2. Call GET /accounts to discover accounts available for selection by account_id, name and email. Follow meta.next_cursor while meta.has_more is true.
  3. Choose an account and use /accounts/{account_id}/... for every account request. The same key works for reads and writes.
GET /api/v1/me
{
  "data": {
    "account_id": "10",
    "email": "owner@example.com",
    "name": "Main account",
    "verified": true,
    "active": true,
    "linked_account_ids": ["10", "20"]
  },
  "meta": { "request_id": "..." }
}

The example key belongs to account 10. To work with another available account 20, keep that key and make a request such as:

curl 'https://semalt.com/api/v1/accounts/20/indexing/urls' \
  -H 'Authorization: Bearer YOUR_API_KEY'

GET /accounts/20 returns account 20’s details. It does not change /me or select an account for later requests. Include account_id in every account path; do not put it in a query parameter or JSON body. Account responses include meta.actor_account_id for the key owner and meta.account_id for the selected account. IDs are returned as strings.

linked_account_ids on /me and account details describes the returned account’s linked group and includes the account itself. It is relationship metadata, not the list of all accounts available to the API key; use /accounts to determine which account IDs are selectable. Access is checked again on each request. Having a shared website from another user does not let you select that user’s account.

What the selected account controls

  • Sites and analytics: the selected account’s own, linked and explicitly shared site records. Use access_type=own for only its own records. New websites belong to the selected account.
  • Site Tags: shared by the selected account’s linked group. Changing a tag affects that group; switching between its members shows the same tags.
  • Keyword Groups: groups keep their individual owners, and linked accounts can view and edit them. New groups belong to the selected account. Editing a linked account’s existing group does not transfer ownership. A group applies to the site’s domain, so different site records for that domain use the same group scope.
  • My SEO: campaigns belong to the selected account. Call GET /accounts/{account_id}/my-seo/campaigns, then use its campaign_id for keywords and backlinks. Campaigns for the same domain in different accounts remain separate. For launched FullSEO campaigns, POST .../keyword-mode switches between auto and manual. Auto mode supports rejecting keywords and restoring rejected keywords to pending; manual mode supports all review statuses, approved-keyword backlink weights, and the one-shot percentage allocation endpoint.
  • Indexing: URL history and balance belong to the selected account. Submitting URLs spends that account’s indexing balance. Linked-account balances are separate.

Check the selected account before submitting indexing URLs. Indexing submissions do not accept an idempotency key: if a response is lost, check that same account’s URL list before retrying. Product limits and campaign requirements apply in every account context.

The global /google-serp/rankings and /ai-analytics/rankings endpoints require authentication but do not take an account_id.

Site records

Site collections preserve each accessible website record without grouping by domain or Search Console property. Repeated domains or properties are intentional when they are available through several accounts.

  • access_type=own — owned by the selected account.
  • access_type=linked — owned by a linked account.
  • access_type=shared — explicitly shared with the selected account.

Hidden and removed records are excluded. Use the returned site id as site_id in that account context. A site’s owner_account.account_id identifies its owner; selecting a linked site does not automatically change the account context. For My SEO, use campaign_id from the selected account’s campaign list instead of site_id.

Account

Discover accounts available for selection, then use account_id for each account operation with the same token.

GET /me

Get the token owner

Always returns the API key owner as account_id. linked_account_ids contains that account and the other members of its linked group. Use GET /accounts to discover account contexts available for selection, then pass a returned account_id in account endpoint paths.

GET /accounts

List available accounts

List account contexts available for selection with this API key. Each record identifies the account using account_id, email and name. A shared website alone does not grant access to its owner’s account context. Follow next_cursor while has_more is true.

limit query · optional · integer · default: 50

Maximum number of records to return in this cursor page. The API may return fewer records; use has_more and next_cursor to continue.

cursor query · optional · string

Continuation cursor from the previous response meta.next_cursor. Omit it for the first page and treat its value as opaque.

search query · optional · string

Case-insensitive text matched against available account names and emails.

GET /accounts/{account_id}

Get a selected account

Returns the selected account’s account_id, email, name, verification state and linked_account_ids. The linked ids describe the selected account’s linked group and include the selected account itself. This does not change the token owner or select an account for later requests. Use GET /accounts to determine which account IDs are selectable with the current API key.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

Sites

Website records available to the selected account.

GET /accounts/{account_id}/sites

List accessible sites

Returns website records available to the selected account. Records are not grouped, so the same domain can appear more than once when it is available through different accounts or properties.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

limit query · optional · integer · default: 50

Maximum number of records to return in this cursor page. The API may return fewer records; use has_more and next_cursor to continue.

cursor query · optional · string

Continuation cursor from the previous response meta.next_cursor. Omit it for the first page and treat its value as opaque.

search query · optional · string

Case-insensitive substring matched against the website domain and, when present, its Search Console property URL.

tag_ids query · optional · array<integer>

Comma-separated site tag ids from GET /accounts/{account_id}/site-tags. By default a site may match any supplied tag; use tag_match=all to require every tag.

tag_match query · optional · string · any | all · default: any

How tag_ids are combined: any returns a site with at least one selected tag; all requires every selected tag.

exclude_tag_ids query · optional · array<integer>

Comma-separated site tag ids. Sites carrying any excluded tag are omitted.

site_type query · optional · string · gsc | manual

Return only Search Console-connected records (gsc) or manually added records (manual).

access_type query · optional · string · own | linked | shared

Filter by the relationship between the selected account and the site record: direct ownership, linked-group ownership, or explicit sharing.

has_search_console query · optional · boolean

When true, return only records connected to a usable Search Console property; when false, return records without one.

POST /accounts/{account_id}/sites

Add a website

Creates or restores a manual website for the selected account. The operation is idempotent by normalized domain: adding the same domain again returns its existing site record.

Request body application/json one JSON object

Website to add. A complete URL is accepted and normalized to its domain.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

domain body · required · string

Public domain or HTTP/HTTPS URL.

JSON body example
{
  "domain": "example.com"
}
GET /accounts/{account_id}/sites/{site_id}

Get one site

Use an id returned by a site collection. The request returns 404 when the site is hidden, removed, unknown, or not accessible to the current account.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

Site Tags

Labels shared by a linked account group for organizing and filtering accessible domains.

GET /accounts/{account_id}/site-tags

List site tags

Returns site tags shared by the selected linked group with the number of accessible domains assigned to each tag.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

POST /accounts/{account_id}/site-tags

Create a site tag

Creates a tag for the linked account group. Repeating the same normalized name updates and returns the existing tag.

Request body application/json one JSON object

Tag name and optional display color.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

name body · required · string

color body · optional · string | null

Optional six-digit hex color.

JSON body example
{
  "name": "Priority",
  "color": "#dc2626"
}
POST /accounts/{account_id}/site-tags/{tag_id}

Update a site tag

Renames a tag and optionally changes its color.

Request body application/json one JSON object

Complete editable tag fields.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

tag_id path · required · integer

Site tag identifier returned by GET /accounts/{account_id}/site-tags.

name body · required · string

color body · optional · string | null

JSON body example
{
  "name": "Important",
  "color": "#dc2626"
}
POST /accounts/{account_id}/site-tags/{tag_id}/delete

Delete a site tag

Permanently deletes the tag and all of its domain assignments. Confirm this destructive action with the user before calling it.

Request body application/json one JSON object

Send an empty JSON object to confirm the request shape.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

tag_id path · required · integer

Site tag identifier returned by GET /accounts/{account_id}/site-tags.

JSON body example
{}
GET /accounts/{account_id}/site-tags/{tag_id}/sites

List sites assigned to a tag

Returns accessible domains assigned to the selected tag. search is a case-insensitive domain substring.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

tag_id path · required · integer

Site tag identifier returned by GET /accounts/{account_id}/site-tags.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

search query · optional · string

Case-insensitive substring matched against assigned domains.

POST /accounts/{account_id}/site-tags/{tag_id}/sites

Assign a tag to sites

Assigns the selected tag to each supplied accessible domain. Existing assignments are left unchanged.

Request body application/json one JSON object

Domains that should receive the tag.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

tag_id path · required · integer

Site tag identifier returned by GET /accounts/{account_id}/site-tags.

domains body · required · array<string>

JSON body example
{
  "domains": [
    "example.com",
    "shop.example.com"
  ]
}
POST /accounts/{account_id}/site-tags/{tag_id}/sites/remove

Remove a tag from sites

Removes the selected tag from supplied accessible domains. Confirm the affected domains with the user before calling it.

Request body application/json one JSON object

Domains from which the tag should be removed.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

tag_id path · required · integer

Site tag identifier returned by GET /accounts/{account_id}/site-tags.

domains body · required · array<string>

JSON body example
{
  "domains": [
    "example.com"
  ]
}

Keyword Groups

Reusable, site-specific keyword collections used as analytics filters.

GET /accounts/{account_id}/sites/{site_id}/keyword-groups

List keyword groups

Returns reusable keyword groups owned by the selected account or its linked accounts for the selected site. Explicit site sharing does not expose another owner's groups.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

POST /accounts/{account_id}/sites/{site_id}/keyword-groups

Create a keyword group

Creates a personal reusable keyword group for the domain represented by site_id.

Request body application/json one JSON object

Name for the new group.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

name body · required · string

JSON body example
{
  "name": "Commercial keywords"
}
POST /accounts/{account_id}/sites/{site_id}/keyword-groups/{group_id}

Rename a keyword group

Renames an editable non-default keyword group.

Request body application/json one JSON object

New group name.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

group_id path · required · integer

Keyword group identifier returned for the selected site.

name body · required · string

JSON body example
{
  "name": "High-intent keywords"
}
POST /accounts/{account_id}/sites/{site_id}/keyword-groups/{group_id}/delete

Delete a keyword group

Permanently deletes an editable non-default group and its keyword membership. Confirm this destructive action before calling it.

Request body application/json one JSON object

Send an empty JSON object to confirm the request shape.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

group_id path · required · integer

Keyword group identifier returned for the selected site.

JSON body example
{}
GET /accounts/{account_id}/sites/{site_id}/keyword-groups/{group_id}/keywords

List group keywords

Returns keyword rows stored in one reusable group. search is a case-insensitive keyword substring.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

group_id path · required · integer

Keyword group identifier returned for the selected site.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

search query · optional · string

Text used to narrow keyword or query results. For Google SERP token search, provide at least four characters.

POST /accounts/{account_id}/sites/{site_id}/keyword-groups/{group_id}/keywords

Add keywords to a group

Adds normalized keywords to an editable group. Exact duplicates are skipped and reported, so retrying the same payload is safe.

Request body application/json one JSON object

Keyword text values to add.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

group_id path · required · integer

Keyword group identifier returned for the selected site.

keywords body · required · array<string>

JSON body example
{
  "keywords": [
    "technical seo audit",
    "managed seo services"
  ]
}
POST /accounts/{account_id}/sites/{site_id}/keyword-groups/{group_id}/keywords/remove

Remove keywords from a group

Removes keyword rows by ids returned by the group keyword list. Confirm the affected rows before calling it.

Request body application/json one JSON object

Keyword row ids to remove.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

group_id path · required · integer

Keyword group identifier returned for the selected site.

keyword_ids body · required · array<integer>

JSON body example
{
  "keyword_ids": [
    123,
    124
  ]
}

Search Console

Google Search Console properties and their analytics.

GET /accounts/{account_id}/search-console/sites

List Search Console properties

Returns accessible Search Console properties with current and previous metrics for each record on this cursor page. By default, the current period ends yesterday and covers the preceding 29 inclusive calendar dates.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

limit query · optional · integer · default: 50

Maximum number of records to return in this cursor page. The API may return fewer records; use has_more and next_cursor to continue.

cursor query · optional · string

Continuation cursor from the previous response meta.next_cursor. Omit it for the first page and treat its value as opaque.

search query · optional · string

Case-insensitive substring matched against the website domain and, when present, its Search Console property URL.

tag_ids query · optional · array<integer>

Comma-separated site tag ids from GET /accounts/{account_id}/site-tags. By default a site may match any supplied tag; use tag_match=all to require every tag.

tag_match query · optional · string · any | all · default: any

How tag_ids are combined: any returns a site with at least one selected tag; all requires every selected tag.

exclude_tag_ids query · optional · array<integer>

Comma-separated site tag ids. Sites carrying any excluded tag are omitted.

access_type query · optional · string · own | linked | shared

Filter by the relationship between the selected account and the site record: direct ownership, linked-group ownership, or explicit sharing.

date_from query · optional · string

Inclusive first calendar date of the requested analytics period in YYYY-MM-DD format. If omitted, the endpoint selects a recent default period.

date_to query · optional · string

Inclusive last calendar date of the requested analytics period in YYYY-MM-DD format. If both dates are supplied in reverse order, site summaries normalize their order.

GET /accounts/{account_id}/search-console/sites/{site_id}/overview

Get Search Console overview

Returns summary cards and daily charts for the exact Search Console property associated with site_id.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

date_from query · optional · string

Inclusive first calendar date of the requested analytics period in YYYY-MM-DD format. If omitted, the endpoint selects a recent default period.

date_to query · optional · string

Inclusive last calendar date of the requested analytics period in YYYY-MM-DD format. If both dates are supplied in reverse order, site summaries normalize their order.

GET /accounts/{account_id}/search-console/sites/{site_id}/traffic

Get a Search Console traffic series

Returns one daily series for a selected query, page, device, or country. metric chooses which measurement is copied into each item.value; every item also contains clicks, impressions, CTR, and average position for context. Use value to select the exact dimension value.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

date_from query · optional · string

Inclusive first calendar date of the requested analytics period in YYYY-MM-DD format. If omitted, the endpoint selects a recent default period.

date_to query · optional · string

Inclusive last calendar date of the requested analytics period in YYYY-MM-DD format. If both dates are supplied in reverse order, site summaries normalize their order.

metric query · optional · string · clicks | impressions | ctr | position · default: position

Selects the measurement written to each traffic-series item.value: clicks is Google result visits, impressions is result appearances, ctr is clicks divided by impressions as a percentage, and position is average Google result position. Each item still includes all four measurements. Default: position.

dimension query · optional · string · query | page | device | country · default: query

Entity represented by value in the traffic series. Use query for a search phrase, page for a page URL, device for desktop/mobile/tablet, or country for a Search Console country code.

value query · optional · string

Exact query text, page URL, device name, or country code whose daily series should be returned. Its meaning is determined by dimension.

device query · optional · string · desktop | mobile | tablet

Restrict Search Console data to one device category.

country query · optional · string

Restrict Search Console data to a canonical country code returned by Search Console, usually a three-character code.

GET /accounts/{account_id}/search-console/sites/{site_id}/keywords

List Search Console keywords

Returns aggregated search queries. search matches query text; metric ranges are inclusive and apply before pagination.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

search query · optional · string

Case-insensitive substring matched against Search Console query text.

date_from query · optional · string

Inclusive first calendar date of the requested analytics period in YYYY-MM-DD format. If omitted, the endpoint selects a recent default period.

date_to query · optional · string

Inclusive last calendar date of the requested analytics period in YYYY-MM-DD format. If both dates are supplied in reverse order, site summaries normalize their order.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

device query · optional · string · desktop | mobile | tablet

Restrict Search Console data to one device category.

country query · optional · string

Restrict Search Console data to a canonical country code returned by Search Console, usually a three-character code.

sort_by query · optional · string · value | keywords | pages | clicks | impressions | ctr | first_time | position · default: impressions

Column used to order aggregated Search Console rows.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

clicks_min query · optional · number

Keep rows with at least this many clicks.

clicks_max query · optional · number

Keep rows with no more than this many clicks.

impressions_min query · optional · number

Keep rows with at least this many impressions.

impressions_max query · optional · number

Keep rows with no more than this many impressions.

ctr_min query · optional · number

Keep rows with CTR at or above this percentage.

ctr_max query · optional · number

Keep rows with CTR at or below this percentage.

position_min query · optional · number

Keep rows whose average position is at least this numeric value.

position_max query · optional · number

Keep rows whose average position is no greater than this numeric value; useful for TOP 10-style filtering.

GET /accounts/{account_id}/search-console/sites/{site_id}/pages

List Search Console pages

Returns aggregated pages. search matches a page URL or path; metric ranges are inclusive and apply before pagination.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

search query · optional · string

Case-insensitive substring matched against a Search Console page URL or path.

date_from query · optional · string

Inclusive first calendar date of the requested analytics period in YYYY-MM-DD format. If omitted, the endpoint selects a recent default period.

date_to query · optional · string

Inclusive last calendar date of the requested analytics period in YYYY-MM-DD format. If both dates are supplied in reverse order, site summaries normalize their order.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

device query · optional · string · desktop | mobile | tablet

Restrict Search Console data to one device category.

country query · optional · string

Restrict Search Console data to a canonical country code returned by Search Console, usually a three-character code.

sort_by query · optional · string · value | keywords | pages | clicks | impressions | ctr | first_time | position · default: impressions

Column used to order aggregated Search Console rows.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

clicks_min query · optional · number

Keep rows with at least this many clicks.

clicks_max query · optional · number

Keep rows with no more than this many clicks.

impressions_min query · optional · number

Keep rows with at least this many impressions.

impressions_max query · optional · number

Keep rows with no more than this many impressions.

ctr_min query · optional · number

Keep rows with CTR at or above this percentage.

ctr_max query · optional · number

Keep rows with CTR at or below this percentage.

position_min query · optional · number

Keep rows whose average position is at least this numeric value.

position_max query · optional · number

Keep rows whose average position is no greater than this numeric value; useful for TOP 10-style filtering.

GET /accounts/{account_id}/search-console/sites/{site_id}/devices

List Search Console devices

Returns aggregated desktop, mobile, and tablet performance. country can narrow the rows before aggregation.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

date_from query · optional · string

Inclusive first calendar date of the requested analytics period in YYYY-MM-DD format. If omitted, the endpoint selects a recent default period.

date_to query · optional · string

Inclusive last calendar date of the requested analytics period in YYYY-MM-DD format. If both dates are supplied in reverse order, site summaries normalize their order.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

device query · optional · string · desktop | mobile | tablet

Restrict Search Console data to one device category.

country query · optional · string

Restrict Search Console data to a canonical country code returned by Search Console, usually a three-character code.

sort_by query · optional · string · value | keywords | pages | clicks | impressions | ctr | first_time | position · default: impressions

Column used to order aggregated Search Console rows.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

clicks_min query · optional · number

Keep rows with at least this many clicks.

clicks_max query · optional · number

Keep rows with no more than this many clicks.

impressions_min query · optional · number

Keep rows with at least this many impressions.

impressions_max query · optional · number

Keep rows with no more than this many impressions.

ctr_min query · optional · number

Keep rows with CTR at or above this percentage.

ctr_max query · optional · number

Keep rows with CTR at or below this percentage.

position_min query · optional · number

Keep rows whose average position is at least this numeric value.

position_max query · optional · number

Keep rows whose average position is no greater than this numeric value; useful for TOP 10-style filtering.

GET /accounts/{account_id}/search-console/sites/{site_id}/countries

List Search Console countries

Returns performance grouped by canonical Google Search Console country code. device can narrow the rows before aggregation.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

date_from query · optional · string

Inclusive first calendar date of the requested analytics period in YYYY-MM-DD format. If omitted, the endpoint selects a recent default period.

date_to query · optional · string

Inclusive last calendar date of the requested analytics period in YYYY-MM-DD format. If both dates are supplied in reverse order, site summaries normalize their order.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

device query · optional · string · desktop | mobile | tablet

Restrict Search Console data to one device category.

country query · optional · string

Restrict Search Console data to a canonical country code returned by Search Console, usually a three-character code.

sort_by query · optional · string · value | keywords | pages | clicks | impressions | ctr | first_time | position · default: impressions

Column used to order aggregated Search Console rows.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

clicks_min query · optional · number

Keep rows with at least this many clicks.

clicks_max query · optional · number

Keep rows with no more than this many clicks.

impressions_min query · optional · number

Keep rows with at least this many impressions.

impressions_max query · optional · number

Keep rows with no more than this many impressions.

ctr_min query · optional · number

Keep rows with CTR at or above this percentage.

ctr_max query · optional · number

Keep rows with CTR at or below this percentage.

position_min query · optional · number

Keep rows whose average position is at least this numeric value.

position_max query · optional · number

Keep rows whose average position is no greater than this numeric value; useful for TOP 10-style filtering.

Google SERP

Google ranking analytics resolved from an accessible website.

GET /accounts/{account_id}/google-serp/sites

List sites with Google SERP metrics

Returns accessible site records with ranking statistics joined by normalized domain. The same domain remains separate when it is accessible through more than one account record. The default date range ends today.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

limit query · optional · integer · default: 50

Maximum number of records to return in this cursor page. The API may return fewer records; use has_more and next_cursor to continue.

cursor query · optional · string

Continuation cursor from the previous response meta.next_cursor. Omit it for the first page and treat its value as opaque.

search query · optional · string

Case-insensitive substring matched against the website domain and, when present, its Search Console property URL.

tag_ids query · optional · array<integer>

Comma-separated site tag ids from GET /accounts/{account_id}/site-tags. By default a site may match any supplied tag; use tag_match=all to require every tag.

tag_match query · optional · string · any | all · default: any

How tag_ids are combined: any returns a site with at least one selected tag; all requires every selected tag.

exclude_tag_ids query · optional · array<integer>

Comma-separated site tag ids. Sites carrying any excluded tag are omitted.

date_from query · optional · string

Inclusive first calendar date of the requested analytics period in YYYY-MM-DD format. If omitted, the endpoint selects a recent default period.

date_to query · optional · string

Inclusive last calendar date of the requested analytics period in YYYY-MM-DD format. If both dates are supplied in reverse order, site summaries normalize their order.

search_engine_id query · optional · integer · default: 1

Numeric search-engine/location identifier returned by Semalt analytics. The default value 1 is the standard engine.

site_type query · optional · string · gsc | manual

Return only Search Console-connected records (gsc) or manually added records (manual).

access_type query · optional · string · own | linked | shared

Filter by the relationship between the selected account and the site record: direct ownership, linked-group ownership, or explicit sharing.

GET /accounts/{account_id}/google-serp/sites/{site_id}/overview

Get Google SERP overview

Returns site statistics for the selected search engine and date range. If an exact snapshot is unavailable, the analytics source may use the nearest earlier snapshot.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

date_from query · optional · string

Inclusive first calendar date of the requested analytics period in YYYY-MM-DD format. If omitted, the endpoint selects a recent default period.

date_to query · optional · string

Inclusive last calendar date of the requested analytics period in YYYY-MM-DD format. If both dates are supplied in reverse order, site summaries normalize their order.

search_engine_id query · optional · integer · default: 1

Numeric search-engine/location identifier returned by Semalt analytics. The default value 1 is the standard engine.

GET /accounts/{account_id}/google-serp/sites/{site_id}/keywords

List Google SERP keyword positions

Returns keyword positions and movement for the domain resolved from site_id. search is a keyword token search and should contain at least four characters. keyword_group_id restricts results to a reusable group visible for this site. Continue cursor pagination with next_token from the result as page_token.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

search_engine_id query · optional · integer · default: 1

Numeric search-engine/location identifier returned by Semalt analytics. The default value 1 is the standard engine.

date query · optional · string

Requested snapshot date in YYYY-MM-DD format. When the exact snapshot is unavailable, Google SERP data may come from the nearest earlier snapshot.

search query · optional · string

Text used to narrow keyword or query results. For Google SERP token search, provide at least four characters.

keyword_group_id query · optional · integer

Restrict results to keywords in this reusable group. Obtain the id from GET /accounts/{account_id}/sites/{site_id}/keyword-groups; an empty group returns no matching rows.

page_url query · optional · string

Exact page URL or path previously returned by Google SERP analytics.

position_group query · optional · string · top1 | top3 | top10 | quick_wins

Convenience filter for position sets: top1 is position 1, top3 is 1–3, top10 is 1–10, and quick_wins is 4–10.

position_change query · optional · string · dynamics | moved_up | moved_down | changed | not_changed | entered | dropped

Filter keywords by movement between snapshots. dynamics means no movement filter.

primary_only query · optional · boolean

When true, return only primary Google SERP position records.

sort_by query · optional · string · key_val | pos | searches | popularity · default: popularity

Column used to order Google SERP keyword rows.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

page_token query · optional · string

Opaque Google SERP keyword cursor from the previous result next_token. Omit it for the first page.

GET /accounts/{account_id}/google-serp/sites/{site_id}/pages

List best Google SERP pages

Returns best-performing pages for the resolved domain. keyword_group_id calculates page metrics only from keywords in a reusable group. page_url and keyword are exact upstream values; numeric minimum and maximum filters are inclusive.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

search_engine_id query · optional · integer · default: 1

Numeric search-engine/location identifier returned by Semalt analytics. The default value 1 is the standard engine.

date query · optional · string

Requested snapshot date in YYYY-MM-DD format. When the exact snapshot is unavailable, Google SERP data may come from the nearest earlier snapshot.

keyword_group_id query · optional · integer

Restrict results to keywords in this reusable group. Obtain the id from GET /accounts/{account_id}/sites/{site_id}/keyword-groups; an empty group returns no matching rows.

page_url query · optional · string

Exact page URL or path previously returned by Google SERP analytics.

keyword query · optional · string

Exact keyword value previously returned by Google SERP analytics.

queries_min query · optional · number

Keep pages with at least this many tracked queries.

queries_max query · optional · number

Keep pages with no more than this many tracked queries.

average_position_min query · optional · number

Keep pages whose average position is at least this value.

average_position_max query · optional · number

Keep pages whose average position is no greater than this value.

share_percent_min query · optional · number

Keep pages whose visibility share is at least this percentage.

share_percent_max query · optional · number

Keep pages whose visibility share is no greater than this percentage.

rating_min query · optional · number

Keep pages whose rating is at least this value.

rating_max query · optional · number

Keep pages whose rating is no greater than this value.

sort_by query · optional · string · total_queries | keywords | avg_pos | share_percent | rating · default: total_queries

Column used to order Google SERP page rows.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

GET /accounts/{account_id}/google-serp/sites/{site_id}/competitors

List Google SERP competitors

Returns the top competitors by shared keywords for the resolved domain.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

search_engine_id query · optional · integer · default: 1

Numeric search-engine/location identifier returned by Semalt analytics. The default value 1 is the standard engine.

date query · optional · string

Requested snapshot date in YYYY-MM-DD format. When the exact snapshot is unavailable, Google SERP data may come from the nearest earlier snapshot.

GET /google-serp/rankings

List global Google SERP rankings

Returns a page of global domain rankings for one search engine and snapshot date.

search_engine_id query · optional · integer · default: 1

Numeric search-engine/location identifier returned by Semalt analytics. The default value 1 is the standard engine.

date query · optional · string

Requested snapshot date in YYYY-MM-DD format. When the exact snapshot is unavailable, Google SERP data may come from the nearest earlier snapshot.

sort_by query · optional · string · rank | authority_linear | authority_percentile | authority_commercial | total_queries | total_pages · default: rank

Column used to order global Google SERP rankings.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

AI Analytics

AI visibility analytics for GPT-4.1 nano and GPT-5 nano.

GET /accounts/{account_id}/ai-analytics/sites

List sites with AI visibility metrics

Returns accessible site records with visibility metrics for the selected public model name. The default model is gpt-5-nano.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

limit query · optional · integer · default: 50

Maximum number of records to return in this cursor page. The API may return fewer records; use has_more and next_cursor to continue.

cursor query · optional · string

Continuation cursor from the previous response meta.next_cursor. Omit it for the first page and treat its value as opaque.

search query · optional · string

Case-insensitive substring matched against the website domain and, when present, its Search Console property URL.

tag_ids query · optional · array<integer>

Comma-separated site tag ids from GET /accounts/{account_id}/site-tags. By default a site may match any supplied tag; use tag_match=all to require every tag.

tag_match query · optional · string · any | all · default: any

How tag_ids are combined: any returns a site with at least one selected tag; all requires every selected tag.

exclude_tag_ids query · optional · array<integer>

Comma-separated site tag ids. Sites carrying any excluded tag are omitted.

model query · optional · string · gpt-4.1-nano | gpt-5-nano · default: gpt-5-nano

AI model dataset to query. gpt-4.1-nano selects GPT-4.1 nano analytics; gpt-5-nano selects GPT-5 nano analytics.

site_type query · optional · string · gsc | manual

Return only Search Console-connected records (gsc) or manually added records (manual).

access_type query · optional · string · own | linked | shared

Filter by the relationship between the selected account and the site record: direct ownership, linked-group ownership, or explicit sharing.

GET /accounts/{account_id}/ai-analytics/sites/{site_id}/overview

Get AI Analytics overview

Returns AI visibility statistics for the domain resolved from site_id and the selected model.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

model query · optional · string · gpt-4.1-nano | gpt-5-nano · default: gpt-5-nano

AI model dataset to query. gpt-4.1-nano selects GPT-4.1 nano analytics; gpt-5-nano selects GPT-5 nano analytics.

GET /accounts/{account_id}/ai-analytics/sites/{site_id}/queries

List AI query positions

Returns query, page, position, and category data. query_id and page_id are exact ids returned by this endpoint; position_group provides common TOP filters without constructing arrays.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

model query · optional · string · gpt-4.1-nano | gpt-5-nano · default: gpt-5-nano

AI model dataset to query. gpt-4.1-nano selects GPT-4.1 nano analytics; gpt-5-nano selects GPT-5 nano analytics.

position_group query · optional · string · top1 | top3 | top10 | quick_wins

Convenience filter for position sets: top1 is position 1, top3 is 1–3, top10 is 1–10, and quick_wins is 4–10.

query_id query · optional · integer

Exact AI Analytics query id returned by a previous query result.

page_id query · optional · integer

Exact AI Analytics page id returned by a previous result.

sort_by query · optional · string · key_val | page_val | pos | ts · default: pos

Column used to order AI query-position rows.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

GET /accounts/{account_id}/ai-analytics/sites/{site_id}/pages

List best AI Analytics pages

Returns best-performing pages for the resolved domain and selected model.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

model query · optional · string · gpt-4.1-nano | gpt-5-nano · default: gpt-5-nano

AI model dataset to query. gpt-4.1-nano selects GPT-4.1 nano analytics; gpt-5-nano selects GPT-5 nano analytics.

sort_by query · optional · string · total_queries | avg_pos | share_percent | rating · default: total_queries

Column used to order AI Analytics page rows.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

GET /accounts/{account_id}/ai-analytics/sites/{site_id}/competitors

List AI competitors

Returns the leading AI visibility competitors for the resolved domain and selected model.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

site_id path · required · integer

Stable site identifier returned by a site collection endpoint.

model query · optional · string · gpt-4.1-nano | gpt-5-nano · default: gpt-5-nano

AI model dataset to query. gpt-4.1-nano selects GPT-4.1 nano analytics; gpt-5-nano selects GPT-5 nano analytics.

GET /ai-analytics/rankings

List global AI visibility rankings

Returns a page of global domain rankings for the selected AI model.

model query · optional · string · gpt-4.1-nano | gpt-5-nano · default: gpt-5-nano

AI model dataset to query. gpt-4.1-nano selects GPT-4.1 nano analytics; gpt-5-nano selects GPT-5 nano analytics.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

My SEO

Campaigns owned by the selected account, addressed by campaign_id. Select another available account to manage its campaigns.

GET /accounts/{account_id}/my-seo/campaigns

List account campaigns

Returns campaigns owned by account_id for accessible, visible domains. Each record contains campaign_id, account_id and domain. Campaigns on the same domain in different accounts remain separate. Use campaign_id for keyword and backlink endpoints.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

limit query · optional · integer · default: 50

Maximum number of records to return in this cursor page. The API may return fewer records; use has_more and next_cursor to continue.

cursor query · optional · string

Continuation cursor from the previous response meta.next_cursor. Omit it for the first page and treat its value as opaque.

search query · optional · string

Case-insensitive substring matched against assigned domains.

campaign_status query · optional · string · draft | launched | paused | cancelled

Return only campaigns in this lifecycle state.

campaign_plan query · optional · string · autoseo | fullseo

Return only campaigns using this plan.

GET /accounts/{account_id}/my-seo/campaigns/{campaign_id}/keywords

List campaign keywords

The campaign_id must belong to account_id. search matches keyword text; target_url is an exact normalized target URL; keyword_group_id restricts results to a reusable group visible for this site. Response fields use the public snake_case contract.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

campaign_id path · required · integer

Campaign identifier returned by the selected account’s campaign list. It must belong to account_id.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

search query · optional · string

Text used to narrow keyword or query results. For Google SERP token search, provide at least four characters.

keyword_group_id query · optional · integer

Restrict results to keywords in this reusable group. Obtain the id from GET /accounts/{account_id}/sites/{site_id}/keyword-groups; an empty group returns no matching rows.

source query · optional · string · gsc | serp | manual

Filter campaign keywords by their source.

status query · optional · string · pending | approved | rejected

Filter campaign keywords by review status.

target_url query · optional · string

Exact normalized target URL assigned to a campaign keyword.

sort_by query · optional · string · keyword | source | url | position | popularity | status | updated_at · default: popularity

Column used to order campaign keywords.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

POST /accounts/{account_id}/my-seo/campaigns/{campaign_id}/keywords

Add manual campaign keywords

Adds keyword and target URL pairs to the campaign_id owned by account_id when it is a launched FullSEO campaign. Duplicate pairs update the existing manual records. Target URLs must belong to the campaign domain.

Request body application/json one JSON object

Manual keyword rows and their initial review state.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

campaign_id path · required · integer

Campaign identifier returned by the selected account’s campaign list. It must belong to account_id.

items body · required · array<object>

approved body · optional · boolean · default: true

true saves as Approved; false saves as Recommended.

JSON body example
{
  "items": [
    {
      "keyword": "technical seo audit",
      "url": "https://example.com/seo-audit"
    }
  ],
  "approved": true
}
POST /accounts/{account_id}/my-seo/campaigns/{campaign_id}/keyword-mode

Set campaign keyword mode

Changes keyword mode for a launched FullSEO campaign. auto keeps keyword review read-only except that rejected keywords can be restored to pending; manual enables approval, rejection, backlink weights, and allocation controls.

Request body application/json one JSON object

Keyword mode to use for the campaign.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

campaign_id path · required · integer

Campaign identifier returned by the selected account’s campaign list. It must belong to account_id.

keyword_mode body · required · string · auto | manual

JSON body example
{
  "keyword_mode": "manual"
}
POST /accounts/{account_id}/my-seo/campaigns/{campaign_id}/keywords/status

Update campaign keyword statuses

Updates the selected campaign keyword ids. In auto mode only rejected keywords may be restored to pending. In manual FullSEO mode, pending, approved, and rejected are supported.

Request body application/json one JSON object

Keyword ids and the requested review status.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

campaign_id path · required · integer

Campaign identifier returned by the selected account’s campaign list. It must belong to account_id.

keyword_ids body · required · array<string>

status body · required · string · pending | approved | rejected

JSON body example
{
  "keyword_ids": [
    "campaign-keyword-id"
  ],
  "status": "approved"
}
POST /accounts/{account_id}/my-seo/campaigns/{campaign_id}/keywords/backlink-weights

Set keyword backlink weights

Sets integer backlink weights for approved keywords in a launched FullSEO campaign using manual keyword mode. Weight values are from 1 to 10000; the resulting backlink share is derived from the total approved weight.

Request body application/json one JSON object

Approved keyword ids and their backlink weights.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

campaign_id path · required · integer

Campaign identifier returned by the selected account’s campaign list. It must belong to account_id.

items body · required · array<object>

JSON body example
{
  "items": [
    {
      "id": "campaign-keyword-id",
      "backlink_weight": 5
    }
  ]
}
POST /accounts/{account_id}/my-seo/campaigns/{campaign_id}/keywords/backlink-allocation

Apply one-shot backlink allocation

Applies the current UI allocation behavior once to all approved keywords in a launched FullSEO campaign using manual keyword mode. Supplied percentages are fixed for this operation; omitted approved keywords share the remainder equally. The allocation is not stored as a persistent fixed-percentage configuration. Call the keyword list endpoint afterwards to inspect the resulting weights and shares.

Request body application/json one JSON object

Keyword ids and their one-shot percentage assignments.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

campaign_id path · required · integer

Campaign identifier returned by the selected account’s campaign list. It must belong to account_id.

items body · required · array<object>

JSON body example
{
  "items": [
    {
      "id": "campaign-keyword-id",
      "percentage": 25.5
    }
  ]
}
GET /accounts/{account_id}/my-seo/campaigns/{campaign_id}/backlinks

List campaign backlinks

The campaign_id must belong to account_id. search matches donor domain, page, question, or associated keyword text. Response fields use the public snake_case contract.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

campaign_id path · required · integer

Campaign identifier returned by the selected account’s campaign list. It must belong to account_id.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

search query · optional · string

Case-insensitive substring matched against donor domain, page, question, and keyword text.

link_type query · optional · string · discussion | article | wiki

Filter backlinks by placement type.

domain_rating query · optional · string · under40 | 40_70 | 70plus

Filter donor domain rating into a simple range: under40, 40_70 (40 inclusive, 70 exclusive), or 70plus.

sort_by query · optional · string · placed | donor | dr | referring_domains | backlinks | rank | top100 · default: placed

Column used to order campaign backlinks.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

Indexing

URLs and indexing balance owned by the selected account. Submissions consume that account’s balance; balances are not pooled.

GET /accounts/{account_id}/indexing/urls

List indexing URLs

Returns indexing URLs and their current crawler status for the selected account. url_contains and domain are independent, case-insensitive substring filters.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

page query · optional · integer · default: 1

One-based result page number. Use 1 for the first page.

page_size query · optional · integer · default: 50

Maximum number of items in one page. Public API responses cap this value at 200; some product datasets may apply a lower internal cap.

url_contains query · optional · string

Case-insensitive substring matched against the complete submitted URL.

domain query · optional · string

Domain or hostname substring. A supplied URL is normalized to its domain before filtering.

status query · optional · string · queued | processing | visited | failed

Filter by readable indexing state.

bot query · optional · string · google | openai | bing

Filter by crawler that processes the URL.

sort_by query · optional · string · url | domain | bot | status | created · default: created

Column used to order indexing records.

sort_direction query · optional · string · ASC | DESC

Sort in ascending (ASC) or descending (DESC) order using sort_by. Defaults are endpoint-specific when omitted.

POST /accounts/{account_id}/indexing/urls

Add URLs to indexing

Submits each unique URL for every selected bot and debits the account indexing balance only for persisted requests. google is the default bot; bing is also supported. This operation does not accept an idempotency key: after an ambiguous network failure, inspect GET /accounts/{account_id}/indexing/urls for the same account before retrying.

Request body application/json one JSON object

Complete URLs and supported crawler names.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

urls body · required · array<string>

bots body · optional · array<string> · default: google

JSON body example
{
  "urls": [
    "https://example.com/",
    "https://example.com/page"
  ],
  "bots": [
    "google"
  ]
}

Report Center

Synchronous PDFs, generation history, and public links. Saved definitions, schedules, and email delivery are not exposed yet.

GET /accounts/{account_id}/report-center/catalog

Discover PDF reports

Returns ready-to-fill definition_template objects. Replace the null ID in each template’s scope with a site_id or campaign_id, then add only fields advertised by that item. For custom PDF branding, also call the white-label endpoint and add its white_label_id to the definition. The response includes comparison modes, PDF row caps, effective actor quotas, and timeout_seconds. Every actor is subject to global capacity limits.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

GET /accounts/{account_id}/report-center/white-labels

Find white labels for PDF branding

Returns up to 50 active white labels with uploaded logos available to the selected linked account group. Take data[].white_label_id and pass it as definition.white_label_id when generating a PDF. Omit white_label_id to use Semalt branding. Use search to narrow results.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

search query · optional · string

GET /accounts/{account_id}/report-center/runs

List report runs

Returns owned and linked-account history, newest first, including browser runs. meta includes limit, has_more and next_cursor. Listing does not issue public links.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

limit query · optional · integer · default: 25

cursor query · optional · string

status query · optional · string · queued | processing | ready | failed | expired

POST /accounts/{account_id}/report-center/runs

Generate a PDF synchronously

Waits for PDF generation and stores the result for 90 days. To use a custom brand, put a white_label_id returned by the white-label endpoint inside definition; the PDF embeds the selected label snapshot. A ready result includes public view_url and download_url: anyone holding a link can read the file. No email is sent. Reuse the same idempotency_key and definition after a lost response; it returns the same run without consuming another generation quota. An in-progress duplicate returns processing. Failed runs return status=failed and error_code; use a new key for another attempt. Replayed ready runs receive new links without extending expiry. Changed definitions with the same key conflict. Standard defaults: 1 concurrent, 3/minute, 50/rolling day. Authorized staff receive higher configured quotas, determined by the key owner. Account and global caps always apply.

Request body application/json one JSON object
account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

definition body · required · object

Start with the report catalog and copy the selected item’s definition_template. Replace its null scope ID, then add only optional fields listed for that item. For custom PDF branding, add white_label_id obtained from GET /accounts/{account_id}/report-center/white-labels. Fixed dates must be ordered and span at most 367 days. latest_snapshot uses source snapshot semantics and a default 28-day reporting window.

execution body · optional · string · default: sync

disposition body · optional · string · inline | attachment · default: inline

idempotency_key body · required · string

JSON body example
{
  "definition": {
    "kind": "report",
    "key": "search_console.site_overview",
    "scope": {
      "site_id": "123"
    },
    "period": {
      "type": "fixed",
      "date_from": "2026-08-01",
      "date_to": "2026-08-31"
    },
    "comparison": {
      "type": "previous_period"
    },
    "white_label_id": "42"
  },
  "execution": "sync",
  "disposition": "inline",
  "idempotency_key": "gsc-123-2026-08"
}
GET /accounts/{account_id}/report-center/runs/{run_id}

Get a report run

Returns status and metadata without creating a public link.

account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

run_id path · required · integer

POST /accounts/{account_id}/report-center/runs/{run_id}/links

Create public PDF links

Creates new links to a ready PDF. Links expire with the original artifact, at most 90 days after generation. Site access changes do not automatically revoke these capability links.

Request body application/json one JSON object
account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

run_id path · required · integer

disposition body · optional · string · inline | attachment · default: inline

JSON body example
{
  "disposition": "inline"
}
POST /accounts/{account_id}/report-center/runs/{run_id}/links/revoke

Revoke public PDF links

Idempotently revokes all currently issued public links to this run. The private artifact remains available in history; authorized callers may explicitly issue new links.

Request body application/json one JSON object
account_id path · required · integer

Account context returned by /me or /accounts. Selects the account for this request. Site operations may return records owned by the selected account, its linked group, or explicitly shared with it. New sites and keyword groups belong to this account, and indexing uses its balance. Repeat account_id in every account request.

run_id path · required · integer

JSON body example
{}
GET /report-files/{report_token}

Open or download a public PDF

Requires only the unguessable token from an issued URL, not an API key. Invalid, expired, or revoked links return 404. Browser settings may override inline display.

report_token path · required · string

download query · optional · string · 1

Use 1 for attachment; omit for inline display.

Synchronous PDF reports

Call GET /accounts/{account_id}/report-center/catalog first. Each item includes a ready-to-fill definition_template. Copy it into the nested definition of POST /accounts/{account_id}/report-center/runs and replace the null scope ID with a value from /sites or /my-seo/campaigns. The item's scope.id_field is the exact field to fill: site_id, campaign_id, or no field for account/global items.

{
  "scope": { "type": "site", "id_field": "site_id", "required": true },
  "definition_template": {
    "kind": "report",
    "key": "search_console.site_overview",
    "scope": { "site_id": null },
    "period": { "type": "latest_snapshot" },
    "filters": {}
  }
}

Use the site or campaign ID returned by /sites or /my-seo/campaigns. Add only filters, table columns, or comparison values listed by the selected catalog item. For custom PDF branding, call GET /accounts/{account_id}/report-center/white-labels, take data[].white_label_id, and add it to definition.white_label_id. The endpoint lists active labels with uploaded logos. Omit white_label_id to use Semalt branding.

GET /api/v1/accounts/20/report-center/white-labels?search=Acme

{
  "data": [
    {
      "white_label_id": "42",
      "name": "Acme Reports",
      "company_name": "Acme Ltd"
    }
  ],
  "meta": { "limit": 50, "has_more": false }
}

For example, use the returned ID at the same level as scope, period, and comparison:

"definition": {
  "kind": "report",
  "key": "search_console.site_overview",
  "scope": { "site_id": "123" },
  "period": { "type": "latest_snapshot" },
  "white_label_id": "42"
}

For example, comparison: { type: "previous_period" } puts the preceding equal-length period into the same Search Console PDF.

The request waits for generation and returns JSON. When status is ready, open view_url or download download_url.

Report links are public: anyone holding one can read the generated PDF for 90 days, unless revoked. Link creation does not extend the file expiry. Choose disposition: inline or attachment to select the returned default url. No email is sent.

Reuse the same key and definition after a lost response. Check processing runs by ID. Failed runs return an error_code; use a new key for a new attempt. History also appears in the dashboard Report Center. Effective quotas and the generation timeout are returned by the catalog; a 429 or 503 response may include Retry-After.

Errors

Errors use application/problem+json. The stable code is suitable for application logic; include request_id when contacting support.

{
  "type": "https://semalt.com/api-docs#errors",
  "title": "Unauthorized",
  "status": 401,
  "code": "invalid_api_key",
  "detail": "The API key is invalid or inactive.",
  "request_id": "..."
}