Skip to content

Optimize API endpoint

Start, poll, and retrieve durable asynchronous Rankability Optimize analyses with retry-safe usage accounting.

Use Optimize to score one existing public page against current search competitors for a target keyword. Agent API and MCP runs are asynchronous and durable: the start request returns an optimization_id immediately, and the result remains available through get and list operations.

This is separate from a persistent Copywriter existing-content project. Optimize saves the scoring run and its evidence, but it does not create or edit a Copywriter draft.

The key needs optimize:run. Before starting work, read GET /api/agent/v1/usage and estimate optimize_page with GET /api/agent/v1/usage/estimate?operation=optimize_page.

POST https://app.rankability.com/api/agent/v1/optimize

A stable Idempotency-Key is required. Repeating the same logical request with the same key returns the same durable run and cannot create a second reservation or provider run.

Terminal window
curl -X POST https://app.rankability.com/api/agent/v1/optimize \
-H "Authorization: Bearer rk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: optimize-example-seo-guide-v1" \
-d '{
"url": "https://example.com/seo-guide",
"keyword": "seo guide",
"language": "en-US",
"client_id": "4746d28b-0a38-43f9-a1ca-5e8402ef73d4"
}'
Field Required Behavior
url Yes Public HTTP or HTTPS page to score
keyword Yes Target query used for competitor research and scoring
language No Language code up to 10 characters; defaults to en-US
client_id No Organization-owned client used to attribute and filter run history

Private IP ranges, localhost, link-local addresses, .local or .internal hosts, and cloud metadata targets are rejected before a reservation or job is created.

The accepted response is 202:

{
"optimization_id": "opt-0123456789abcdef",
"status": "queued",
"client_id": "4746d28b-0a38-43f9-a1ca-5e8402ef73d4",
"url": "https://example.com/seo-guide",
"keyword": "seo guide",
"language": "en-US",
"created_at": "2026-08-24T20:00:00.000Z",
"started_at": null,
"completed_at": null,
"error": null
}

Use the status view while work is queued or running:

GET /api/agent/v1/optimizations/:optimization_id?view=status

Statuses are queued, running, complete, or failed. After completion, request view=summary for the score, source word count, competitor count, duration, and billing finalization state. Use view=full only when the complete entity, category, scoring, and competitor evidence is needed.

GET /api/agent/v1/optimizations/:optimization_id?view=full

The full response returns the saved upstream Optimize result under result. A successful result can include rankabilityScore, categoryScores, scoreDetails, entities, sourceWordCount, competitorCount, competitors, and duration.

Competitor pages that cannot be fetched are omitted. A smaller comparison set means less evidence; it does not mean Rankability verified every result page. Scores are dated observations because search results and page content change.

GET /api/agent/v1/optimizations?client_id=:clientId&status=complete&limit=25&offset=0

History is organization-scoped, newest first, and capped at 100 rows per page. Optional filters are client_id, status, keyword, and url. List results are summaries and do not repeat full result payloads.

Failed provider work releases the run’s reservation. Successful work finalizes that same reservation once. If finalization needs reconciliation after a usable result exists, the artifact remains available with billing_status: reconciliation_pending; the system does not create an unrelated second debit.

Do not repeatedly poll the full view. Poll status with a bounded interval, then retrieve the full result once. A terminal failed run remains auditable; use a new idempotency key only when the user approves a genuinely new attempt.

Status Code or state Action
400 validation_error Correct invalid or unsafe input
400 idempotency_key_required Supply one stable retry key
401 unauthorized Replace or correct the key
403 forbidden Grant optimize:run
404 not_found Confirm the run belongs to the active organization
429 usage_limit_reached or rate_limit_exceeded Wait until the returned recovery time
terminal failed Read the saved error and start a separately approved retry with a new key

See API usage, rate limits, and errors for the shared approval and usage contract.