docs / endpoint
POST /v1/keywords/difficulty
Keyword difficulty (0-100) per keyword; unscored keywords return pending and are scored for a later call.
Credits: 110 credits per call.
Timeout: 120s
Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
keywords |
array | required | — | Keywords to score difficulty for. Required, non-empty. Array of string. Max 500 items. |
location |
any | required | — | Google Ads geotarget ID, or a location name (e.g. a country/state/city name). Required. Look one up with /v1/locations. |
language |
string | required | — | ISO language code. Required. |
tag |
string | optional | — | Optional client-defined label forwarded to the upstream task for your own bookkeeping; not echoed back in the response. |
Request
→ requestPOST /v1/keywords/difficulty
POST /v1/keywords/difficulty HTTP/1.1
Authorization: Bearer sof_live_your_key_here
Content-Type: application/json
{
"keywords": [
"buy running shoes",
"cold keyword"
],
"location": 2840,
"language": "en"
}
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": "keyw_bdfyxosao3hbn5vhdo362aki",
"request_id": "req_tjpeqht54vd6bjgaxqnfxnciju",
"object": "keyword_difficulty",
"created_at": "2026-08-09T07:19:28Z",
"elapsed_ms": 180,
"cache": "miss",
"credits": {
"charged": 110,
"balance": 9857
},
"data": {
"items_count": 2,
"items": [
{
"keyword": "buy running shoes",
"difficulty": 42,
"status": "available"
},
{
"keyword": "cold keyword",
"difficulty": null,
"status": "pending"
}
]
}
}
Response fields
What each field in data (above) means.
| Field | Description |
|---|---|
data.items_count |
Number of entries in items. |
data.items |
One row per requested keyword. |
data.items[].keyword |
The keyword. |
data.items[].difficulty |
0-100 difficulty score, or null while status is "pending". |
data.items[].status |
"available" once scored, or "pending" if the keyword needed a fresh scrape that hadn't completed yet -- retry the same keyword later to resolve it. |