REST

Keywords

Retrieve keyword trend data and managed tracked keyword targets. The GET endpoint returns GSC data or tracked targets depending on the view parameter. POST upserts tracked keywords; DELETE removes them by ID.

GET/api/v1/sites/:siteId/keywords

Keyword trends and tracked targets

Without ?view=targets returns GSC keyword trend data (impressions, clicks, CTR, position with period-over-period changes). With ?view=targets returns the tracked keyword target list with latest rank data.

Request

bash
curl -X GET \
  'https://letoseo.com/api/v1/sites/:siteId/keywords' \
  -H 'Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

Path parameters

NameTypeRequiredDescriptionDefault
siteIduuidrequiredThe site UUID.

Query parameters

NameTypeRequiredDescriptionDefault
view"targets"optionalPass "targets" to return the tracked keyword target list instead of GSC trend data.
date_range"7d" | "28d" | "90d"optionalTime range for GSC trend data. Ignored when view=targets.28d
limitintegeroptionalMaximum number of results. Max 100.25
query_filterstringoptionalSubstring filter applied to keyword strings. Case-insensitive. Only applies to the default (trends) view.
intentstringoptionalFilter by search intent. Only applies when view=targets.
priority"money" | "standard" | "long-tail"optionalFilter by keyword priority. Only applies when view=targets.
sortstringoptionalColumn to sort by when view=targets.keyword
order"asc" | "desc"optionalSort direction when view=targets.asc

Responses

200Keyword trend data (default) or tracked keyword targets (view=targets).
json
{
  "data": [
    {
      "query": "example keyword",
      "impressions": 1240,
      "clicks": 62,
      "ctr": 0.05,
      "position": 7.4,
      "impressions_prev": 1100,
      "clicks_prev": 55,
      "position_prev": 8.1
    },
    {
      "query": "acme tool review",
      "impressions": 640,
      "clicks": 19,
      "ctr": 0.03,
      "position": 14.2,
      "impressions_prev": 580,
      "clicks_prev": 18,
      "position_prev": 15
    }
  ],
  "_meta": {
    "generated_at": "2025-01-15T10:30:00.000Z",
    "site_id": "00000000-0000-0000-0000-000000000001"
  }
}
404Site not found.
json
{
  "error": "Site not found"
}
POST/api/v1/sites/:siteId/keywords

Add or update tracked keywords

Upserts keyword tracking targets for a site. If a keyword already exists (matched on site_id + keyword + location_code + device), its fields are updated. Returns 201 with the upserted rows. Maximum 100 keywords per request; maximum 200 keywords per site.

Request

bash
curl -X POST \
  'https://letoseo.com/api/v1/sites/:siteId/keywords' \
  -H 'Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
    "keywords": [
      {
        "keyword": "example keyword",
        "priority": "money",
        "tracking_frequency": "daily",
        "device": "desktop",
        "source": "manual"
      },
      {
        "keyword": "acme tool review"
      }
    ]
  }'

Path parameters

NameTypeRequiredDescriptionDefault
siteIduuidrequiredThe site UUID.

Request body (application/json)

NameTypeRequiredDescriptionDefault
keywordsKeywordInput[]requiredArray of keyword objects to upsert. Each object must include at least "keyword".

Example

json
{
  "keywords": [
    {
      "keyword": "example keyword",
      "priority": "money",
      "tracking_frequency": "daily",
      "device": "desktop",
      "source": "manual"
    },
    {
      "keyword": "acme tool review"
    }
  ]
}

Responses

201Upserted keyword target rows.
json
{
  "data": [
    {
      "id": "00000000-0000-0000-0000-000000000021",
      "site_id": "00000000-0000-0000-0000-000000000001",
      "keyword": "example keyword",
      "priority": "money",
      "tracking_frequency": "daily",
      "device": "desktop",
      "source": "manual",
      "search_intent": null,
      "location_code": 2840,
      "created_at": "2025-01-15T10:30:00.000Z",
      "updated_at": "2025-01-15T10:30:00.000Z"
    },
    {
      "id": "00000000-0000-0000-0000-000000000022",
      "site_id": "00000000-0000-0000-0000-000000000001",
      "keyword": "acme tool review",
      "priority": "standard",
      "tracking_frequency": "daily",
      "device": "desktop",
      "source": "manual",
      "search_intent": null,
      "location_code": 2840,
      "created_at": "2025-01-15T10:30:01.000Z",
      "updated_at": "2025-01-15T10:30:01.000Z"
    }
  ],
  "_meta": {
    "generated_at": "2025-01-15T10:30:00.000Z",
    "site_id": "00000000-0000-0000-0000-000000000001"
  }
}
400Validation error: keywords array missing or empty, invalid enum value, or would exceed the 200-keyword site limit.
json
{
  "error": "keywords array is required"
}
404Site not found.
json
{
  "error": "Site not found"
}
DELETE/api/v1/sites/:siteId/keywords

Remove tracked keywords

Deletes keyword tracking targets by ID. Requires a JSON body with the array of IDs to delete. Returns 204 with an empty body on success. Maximum 100 IDs per request.

Request

bash
curl -X DELETE \
  'https://letoseo.com/api/v1/sites/:siteId/keywords' \
  -H 'Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  -H 'Content-Type: application/json' \
  -d '{
    "ids": [
      "00000000-0000-0000-0000-000000000021",
      "00000000-0000-0000-0000-000000000022"
    ]
  }'

Path parameters

NameTypeRequiredDescriptionDefault
siteIduuidrequiredThe site UUID.

Request body (application/json)

NameTypeRequiredDescriptionDefault
idsuuid[]requiredArray of keyword target UUIDs to delete. Max 100.

Example

json
{
  "ids": [
    "00000000-0000-0000-0000-000000000021",
    "00000000-0000-0000-0000-000000000022"
  ]
}

Responses

204Keywords deleted. Response body is empty.
400ids array missing, empty, or contains invalid UUIDs.
json
{
  "error": "ids array is required"
}
404Site not found.
json
{
  "error": "Site not found"
}