POST /api/v1/analyze
The complete reference for the public analysis endpoint: authentication, request body, every response field, errors, cost and behavior.
Last updated 2026-08-06
Summary#
POST /api/v1/analyze is the only public endpoint in the Metric Vault API. It takes a domain and returns a single JSON object containing a competitive analysis: authority and SEO scores, estimated traffic, brand sentiment, market position, a content-gap score, a threat level, keywords, competitors, opportunities, weaknesses and a written summary. It requires an mv_live_ API key, the Enterprise plan, and it costs 6 credits per successful call.
Overview#
The endpoint is synchronous. One request produces one complete analysis in the response body; there is no job id, no polling and no callback. The call runs a language-model analysis inside the request, so expect several seconds of latency and set a generous client timeout.
Important: The response is a model-generated expert estimate of the domain, not a measurement pulled from a search-data provider. Two calls for the same domain can return slightly different numbers. Treat the values as directional intelligence, not as metered analytics. The measured, provider-backed figures live in the dashboard tools. See AI models used across the platform and Where the data comes from for how the two differ.
Endpoint#
| Property | Value |
|---|---|
| Method | POST |
| URL | https://metricvaultai.com/api/v1/analyze |
| Authentication | Authorization: Bearer mv_live_... |
| Content type | application/json |
| Plan required | Enterprise, re-checked on every call |
| Credit cost | 6, metered as the tool domain_overview |
| Idempotent | No. Every call runs a fresh analysis and is charged |
| Caching | None. Responses are not cached or deduplicated |
| CORS | Access-Control-Allow-Origin: * |
Request headers#
| Header | Required | Value |
|---|---|---|
Authorization | Yes | Bearer followed by the full key. Any other scheme is treated as missing |
Content-Type | Yes | application/json |
Request body#
| Field | Type | Required | Notes |
|---|---|---|---|
url | string | One of url or domain | The subject of the analysis. A bare domain such as example.com or a full URL both work |
domain | string | One of url or domain | Alias for url. Used only if url is absent |
Any other field in the body is ignored. An unparseable body is treated as an empty object, which then fails the missing-target check.
{ "url": "example.com" }Response#
200 OK
{
"ok": true,
"url": "example.com",
"analysis": { }
}| Envelope field | Type | Notes |
|---|---|---|
ok | boolean | Always true on success |
url | string | Echoes the value you sent |
analysis | object | The payload, described below |
The analysis object#
| Field | Type | Range or values | Meaning |
|---|---|---|---|
domainAuthority | number | 1 to 100 | Estimated overall domain strength |
seoScore | number | 1 to 100 | Estimated search-performance health |
estimatedTraffic | string | For example "1.2M/mo" | Estimated monthly organic traffic, formatted for display |
brandSentiment | string | Very Positive, Positive, Neutral, Negative | Overall tone of brand mentions |
sentimentScore | number | 1 to 100 | Numeric form of the sentiment reading |
marketPosition | string | Free text | One-line description of where the brand sits in its category |
contentGapScore | number | 1 to 100 | Estimated size of the content opportunity against competitors |
threatLevel | string | Low, Medium, High, Critical | Competitive pressure on the domain |
topKeywords | string array | 5 entries | Highest-value keyword themes for the domain |
competitors | string array | 3 entries | Closest competing domains |
opportunities | string array | Short entries | Where the domain has headroom |
weaknesses | string array | Short entries | Where the domain is exposed |
summary | string | 2 to 3 sentences | Executive summary of the analysis |
The array lengths above are what the endpoint asks for and normally returns. Write your client so that a missing field or a differently-sized array does not throw: read defensively rather than destructuring blindly.
Errors#
Responses are JSON with an error string, and sometimes a machine-readable code. The request stops at the first gate that fails.
| HTTP | code | Body message | Cause | Fix |
|---|---|---|---|---|
| 401 | — | Missing API key. Send header: Authorization: Bearer mv_live_... | No Authorization header, or a scheme other than Bearer | Send the header exactly as shown |
| 401 | — | Invalid or revoked API key | The key is unknown, truncated, or revoked | Check the value end to end, or create a new key |
| 403 | upgrade_required | This feature requires the Enterprise plan. Your account is on <Plan>. Upgrade to unlock it. | The key's owner is not on Enterprise now | Restore the plan. The same key resumes working |
| 403 | account_suspended | This account is suspended. Please contact support. | The owning account is suspended | Contact support@metricvaultai.com |
| 400 | — | Provide a JSON body: { "url": "example.com" } | Neither url nor domain was present | Send one of them |
| 429 | quota_exceeded | You've used all <N> premium reports on the <PLAN> plan this month. … | The month's credit allowance is spent | Wait for reset_date in the response, or upgrade |
| 503 | plan_check_failed | Plan check temporarily unavailable, please retry. | The plan lookup could not complete | Retry. Nothing was charged |
| 503 | quota_check_failed | Usage check temporarily unavailable, please retry. | The usage lookup could not complete | Retry. Nothing was charged |
| 500 | — | The upstream error message | The analysis call failed or its output could not be parsed | Retry once. If it persists, contact support |
The 429 body also carries plan, used, quota, cost, reset_at in ISO form, reset_date in readable form, days_until_reset and upgrade_url. The full catalogue is in Error codes.
Order of checks#
The endpoint applies its gates in a fixed order, which determines what you are charged:
| Step | Check | Charged if it fails? |
|---|---|---|
| 1 | Authorization header present and parseable | No |
| 2 | Key exists and is not revoked | No |
| 3 | Key owner is currently on Enterprise | No |
| 4 | Account is not suspended, and has 6 credits available | No |
| 5 | Body contains url or domain | No |
| 6 | Analysis runs | Charged only on success |
A 200 has always been metered. Anything else has not.
Side effects of a successful call#
| Effect | Detail |
|---|---|
| Credits | 6 deducted from the owning account's current-month allowance |
| Usage attribution | Recorded against the tool name domain_overview |
| Key metadata | The key's last_used_at timestamp is updated |
| Library | Nothing is saved. API results do not appear in Saved Work |
Metering is best-effort in the sense that a failure to record usage does not fail your request. It does not mean calls are free.
Limits#
| Limit | Value |
|---|---|
| Credit cost | 6 per call |
| Monthly allowance (Enterprise) | 10,000 credits |
| Calls per month at that allowance | 1,666 |
| Hourly fair-use limit | Does not apply. That limit covers light tools costing fewer than 3 credits |
| Request body size | No documented cap; the body is a single short JSON object |
| Concurrency | Not limited by the endpoint. Your monthly quota is the real ceiling |
Example#
curl -sS -X POST https://metricvaultai.com/api/v1/analyze \
-H "Authorization: Bearer mv_live_3f9a1c7d4b28e05a6f13c9d720b48e1a5c6d7f0293a4b1c8" \
-H "Content-Type: application/json" \
-d '{"url": "notion.so"}'{
"ok": true,
"url": "notion.so",
"analysis": {
"domainAuthority": 86,
"seoScore": 81,
"estimatedTraffic": "9.4M/mo",
"brandSentiment": "Positive",
"sentimentScore": 84,
"marketPosition": "Leading all-in-one workspace for teams and individuals",
"contentGapScore": 46,
"threatLevel": "Medium",
"topKeywords": ["notion templates", "note taking app", "project management tool", "wiki software", "notion ai"],
"competitors": ["coda.io", "clickup.com", "obsidian.md"],
"opportunities": ["Template-led landing pages for niche workflows", "Comparison content against task-first competitors"],
"weaknesses": ["Limited depth on enterprise governance queries", "Community content outranks owned pages on how-to intent"],
"summary": "Notion converts strong branded demand into broad category visibility, with template and how-to queries driving most non-branded entry. The largest gap is owned depth on workflows where community content currently ranks first."
}
}More languages are in Code examples.
Screenshots#
See also
Was this article helpful?
Thanks — feedback noted for the docs team.