Change the notes, source, research figures or target page of a tracked keyword.
Send only the fields to change; null clears one. Pass expected_updated_at from the last read so a change made elsewhere answers 409 STALE_VERSION instead of being overwritten. The Google position history is never changed by this call.
https://app.softsolz.uk/api/v1/services/seo/sites/{site_id}/keywords/{keyword_id}Recent Requests
Kept only in this browserPath Params
site_idstringrequiredkeyword_idstringrequiredHeaders
AuthorizationstringrequiredBearer token: `Bearer sk_live_...` (or `sk_test_...` for sandbox). A login token will not work here.
Idempotency-KeystringOptional idempotency key for safe retries.
Body Params
notesstring | nullYour notes about the keyword, up to 1000 characters.
source_labelstring | nullWhere the research came from, up to 80 characters. Shown as "From <source>".
their_monthly_searchesinteger | nullMonthly searches as estimated by your research tool, 0 or more. Stored and shown as that tool estimate, never as a Google figure.
their_difficultyinteger | nullDifficulty from 0 to 100 as scored by your research tool. Stored and shown as that tool estimate.
target_urlstring | nullThe page that should rank for the keyword: a full address on the website domain (with or without www) or a path starting with /. Anything else is refused with 400 target_url_not_on_site.
expected_updated_atstringupdated_at from your last read of the keyword.
Response
Response Body
idstringTracked keyword id. Use it as keyword_id.site_idstringThe website it belongs to.query_textstringNormalised search text.notesstring | nullYour notes about the keyword, up to 1000 characters.source_labelstring | nullWhere the research came from, up to 80 characters. Shown as "From <source>".their_monthly_searchesinteger | nullMonthly searches as estimated by your research tool, 0 or more. Stored and shown as that tool estimate, never as a Google figure.their_difficultyinteger | nullDifficulty from 0 to 100 as scored by your research tool. Stored and shown as that tool estimate.target_urlstring | nullThe page that should rank, as a full address.added_viastringHow it was added: dashboard, api or connected_app.added_by_labelstring | nullThe app or key that added it.created_atstringWhen tracking started.updated_atstringSend it back as expected_updated_at when you change the keyword.Request
curl --request PATCH \ --url https://app.softsolz.uk/api/v1/services/seo/sites/{site_id}/keywords/{keyword_id} \ --header 'Authorization: Bearer sk_live_your_key' \ --header 'Content-Type: application/json' \ --data '{ "notes": "Main money keyword.", "source_label": "Ahrefs via Claude", "their_monthly_searches": 2400, "their_difficulty": 35, "target_url": "/sourdough-starter"}'Credentials
Sent as a Bearer token and used in the samples above and in Try it. Kept only in this browser tab until you close it. Use an sk_test_ key to stay in your sandbox.
Response · 200
{ "data": { "id": "3f2b9c44-8f4e-4d0a-9c1b-2a7d6e5f1a23", "site_id": "3f2b9c44-8f4e-4d0a-9c1b-2a7d6e5f1a23", "query_text": "sourdough starter", "notes": "Main money keyword.", "source_label": "Ahrefs via Claude", "their_monthly_searches": 2400, "their_difficulty": 35, "target_url": null, "added_via": "connected_app", "added_by_label": "Claude", "created_at": "2026-09-01T09:00:00.000Z", "updated_at": "2026-09-01T09:00:00.000Z" }}