docs / endpoint

POST /v1/domains/gap

Keyword gap between two domains: opportunity, shared, or unique rankings, volume-enriched.

Credits: 15 credits per call. Timeout: 60s

Parameters

NameTypeRequiredDefaultDescription
domains array required Put your own domain first -- every mode is defined relative to domains[0]. Array of string. Max 2 items.
mode string optional "gap" gap: keywords domains[1] ranks for that domains[0] does not. shared: both rank. unique: only domains[0] ranks. Optional, default "gap".
engine string optional "google" Optional, default "google". Same enum as /v1/search.
location integer optional 2840 Google Ads geotarget ID. Optional, default 2840 (United States). Look one up with /v1/locations.
language string optional "en" ISO language code. Optional, default "en".
device string optional "desktop" One of: desktop, mobile. Optional, default "desktop".
date_from string optional ISO YYYY-MM-DD, inclusive. Optional, default 730 days ago -- sets how far back in the archive the comparison reaches.
limit integer optional 100 Optional, default 100. 1-1000.
offset integer optional 0 Optional, default 0. 0-10000.

Request

→ requestPOST /v1/domains/gap
POST /v1/domains/gap HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json

{
  "domains": [
    "semrush.com",
    "ahrefs.com"
  ],
  "mode": "gap",
  "engine": "google",
  "location": 2840,
  "language": "en",
  "device": "desktop",
  "limit": 100,
  "offset": 0
}

Response

Wrapped in the standard envelope -- id, object, created_at, elapsed_ms, cache, credits -- documented once on The Contract. The body below is a real envelope with this endpoint's data shape; values vary per request, and a marks an array cut short for display.

← response200
{
  "id": "doma_4iwnb3n4nfvvsw55wnpwp2fm",
  "request_id": "req_5ynm5drlkzbkde52tuuqp3yloy",
  "object": "domain_gap",
  "created_at": "2026-08-09T07:19:28Z",
  "elapsed_ms": 180,
  "cache": "miss",
  "credits": {
    "charged": 15,
    "balance": 9857
  },
  "data": {
    "mode": "gap",
    "domains": [
      "semrush.com",
      "ahrefs.com"
    ],
    "items": [
      {
        "keyword": "search engine optimization",
        "volume": 18100,
        "ranks": [
          null,
          {
            "rank": 27,
            "url": "https://ahrefs.com/blog/what-is-seo/",
            "date": "2026-06-28"
          }
        ]
      },
      "…"
    ],
    "totals": [
      2834,
      1315
    ],
    "matched_count": 409,
    "coverage": {
      "from": "2026-06-28",
      "observations": 409
    },
    "limit": 100,
    "offset": 0
  }
}

Response fields

What each field in data (above) means.

FieldDescription
data.mode Comparison mode that was applied: gap, shared, or unique.
data.domains The two domains you compared, in the order you sent them.
data.items One row per matching keyword, up to limit.
data.items[].keyword The keyword.
data.items[].volume Search volume for the keyword.
data.items[].ranks Two-element array positionally aligned to domains: ranks[0] is domains[0]'s rank, ranks[1] is domains[1]'s rank on this keyword. Each entry is null (that domain doesn't rank) or {rank, url, date}.
data.totals Two-element array positionally aligned to domains: total ranked-keyword count for each domain.
data.matched_count Total keywords matching mode, before limit/offset truncation.
data.coverage How much of the rankings archive this comparison drew from.
data.coverage.from Earliest observation date among the returned items, floor-clamped to date_from.
data.coverage.observations Same as matched_count.
data.limit Page size actually used (echoes the request).
data.offset Pagination offset actually used (echoes the request).