Reference

API documentation

Everything ships under one envelope, one auth header and one vocabulary. Base URL: https://seometricsapi.com

Authentication

One bearer header

Every request (except /v1/health and the public tool endpoints) carries your key in the Authorization header. Keys come from the signup page, look like sk_live_pub_…, and are stored by us only as a hash. A missing or invalid key answers 401.

$ curl -H "Authorization: Bearer sk_live_pub_YOUR_KEY" \ "https://seometricsapi.com/v1/domains/example.com?fields=rating,traffic"

The envelope

data · meta · error, on every response

{ "data": { "domain": "apnews.com", "requested": "apnews.com", "domain_rating": 91, "ahrefs_rank": 412, "monthly_visits": 105300000, "monthly_visits_basis": "total", "organic_monthly_visits": 38200000, "sources": { "domain_rating": { "provider": "ahrefs", "fetched_at": "2026-08-28T09:14:02Z", "status": "ok" }, "monthly_visits": { "provider": "similarweb", "fetched_at": "2026-08-27T22:41:55Z", "status": "ok" } } }, "meta": { "resource": "domain", "request_id": "req_01J6XY0M9…", "cache": "hit", "age_seconds": 254407, "cost_units": 0, "degraded": false }, "error": null }
  • Numbers stay numbers. 105300000, never "105M+" — formatting is your UI's job.
  • null means unknown. Never zero, never a placeholder. The matching sources entry says why: no_data, provider_error, disabled or not_requested.
  • Provenance per field. Each metric names its provider and fetch time — stamp your own freshness from fetched_at, not from the moment you asked.
  • meta.cache + meta.cost_units. hit costs 0 credits; a fresh fetch costs 1 per provider call. degraded: true flags a stale-but-served answer.

Endpoints

The surface

MethodPathReturnsNotes
GET/v1/domains/{domain}The domain resourceThe workhorse. fields, traffic_fallback, country, max_age.
POST/v1/domains:batchResults, or a jobUp to 200 domains; above 25 it answers 202 with a job. Growth plans and up.
POST/v1/domains:aggregateBundle statsdomain_rating_avg, domain_rating_max, monthly_visits_sum over a list.
GET/v1/jobs/{job_id}Batch progresstotal / done / ok / no_data / failed; results once terminal.
GET/v1/keywordsKeyword metricsq = up to 10 comma-separated phrases; volume, difficulty, CPC + currency.
GET/v1/serpSERP snapshotq, plus country, language, limit, type. Organic results with serp_position; data.engine always named.
GET/v1/indexIndex checktarget (a domain or a full URL) plus samples (0–10). Reports presence in Google's index.
GET/v1/faviconVerified favicon URLProbed, size-checked, never a blank placeholder.
GET/v1/usageYour consumptionCurrent period: events, credits spent, cache hits, your limits.
GET/v1/healthService statusAnonymous. Database + provider availability.
# Domain metrics, scoped to what you pay for $ curl -H "Authorization: Bearer $KEY" \ "https://seometricsapi.com/v1/domains/nytimes.com\ ?fields=rating,traffic,countries,engagement"
# Keyword volumes, difficulty, CPC $ curl -H "Authorization: Bearer $KEY" \ "https://seometricsapi.com/v1/keywords\ ?q=seo%20api,domain%20rating&country=US"
# SERP snapshot $ curl -H "Authorization: Bearer $KEY" \ "https://seometricsapi.com/v1/serp\ ?q=affordable%20seo%20api&country=US&limit=10"
# Am I indexed? · What have I spent? $ curl -H "Authorization: Bearer $KEY" \ "https://seometricsapi.com/v1/index?target=example.com" $ curl -H "Authorization: Bearer $KEY" \ "https://seometricsapi.com/v1/usage"

Field groups

Ask only for what you need

The fields parameter scopes both the response and the spend. Default: rating,traffic,countries.

GroupFields included
ratingdomain_rating (0–100), ahrefs_rank
trafficmonthly_visits (+ monthly_visits_basis), organic_monthly_visits
countriestop_countries[{country_code, share}], share is a fraction 0–1
engagementbounce_rate, pages_per_visit, time_on_site_seconds, month, traffic_sources
rankstraffic_ranks — global, country and category popularity ranks
historymonthly_visits_history — recent months of visit estimates
sitesite — name, title, description, category
faviconfavicon_url
allEverything above

Errors, limits & quotas

Refusals you can program against

Every failure is the same envelope with data: null and an error of {code, message, retriable}.

CodeHTTPRetriableMeaning
invalid_input400noThe request could not be understood; the message names the parameter.
unauthorized401 / 403noNo usable key (401), or the key lacks the required scope (403).
not_found404noThe target can't be identified — a malformed domain, an unknown job.
rate_limited429yesPer-minute burst limit. Back off for Retry-After seconds.
quota_exceeded429noMonthly credits spent. Resets on the 1st (UTC); upgrading lifts it immediately.
provider_unavailable503yesAn upstream provider is down; cached data may still be served with degraded: true.

Rate-limit state travels in headers — X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, plus Retry-After on a refusal. Cache hits are charged at a tenth of the per-minute weight, so a well-cached integration is effectively unthrottled. The monthly credit meter is the one /v1/usage reports — the same number that triggers quota_exceeded, so what you see is what refuses you.

Ready to make the first call?

A free key takes one email and carries 100 credits a month.


Start now

100 free credits a month, forever. Upgrade only when you outgrow them.

Get free API key

© SEO Metrics API