Base URL: https://dokeo-api.fly.dev. Every endpoint is a JSON POST or GET. Bearer-token auth, HMAC-verified, rate-limited.
Authentication
Pass your tenant API key as a Bearer token. Get a key from your admin or by calling POST /api/v1/admin/keys.
# All requests need an Authorization header with a Bearer token
curl https://dokeo-api.fly.dev/api/v1/scan \
-H "Authorization: Bearer dk_your_tenant_key" \
-H "Content-Type: application/json" \
-d '{
"content": "Your blog post here...",
"content_type": "blog"
}'Response shape
Every scan returns the same envelope. verdict is the worst of five severities, most to least severe: BLOCKER (ships never), FAIL, WARNING, OPTIMIZATION (a suggestion, never blocks), or PASS. scores.overall is 0-100. checks_detail[] has one row per check with its own severity, reasons, and metrics.
{
"slug": "my-post",
"verdict": "WARNING",
"content_type": "blog",
"word_count": 1245,
"report": {
"scores": {
"overall": 87,
"seo": 92,
"aeo": 81,
"geo": 88
},
"meta": {
"pass_count": 6, "blocker_count": 0, "fail_count": 0,
"warning_count": 1, "optimization_count": 0
},
"checks_detail": [
{
"check": "structure",
"status": "PASS",
"severity": "PASS",
"reasons": ["1245 words, in target band"],
"metrics": { "word_count": 1245, "h2_count": 6 }
}
],
"action_items": [
{ "priority": "recommended", "action": "Add an FAQ section for AEO" }
],
"inline_issues": []
}
}Endpoints
/api/v1/scanScore inline content. 1 credit per call.
| Field | Type | Notes |
|---|---|---|
| content | string | Required The post body |
| content_type | string | Default: blog One of 17 types |
| title | string | Optional Post title |
| slug | string | Optional Post slug |
| primary_keyword | string | Optional Main SEO keyword |
| strictness | string | Default: balanced strict | balanced | permissive |
/api/v1/scan/urlFetch + score a URL. SSRF-guarded (blocks private/loopback IPs).
| Field | Type | Notes |
|---|---|---|
| url | string | Required https URL |
| content_type | string | Default: blog |
| strictness | string | Default: balanced |
/api/v1/scan/blogScore every post on a blog (discovered via RSS/sitemap).
| Field | Type | Notes |
|---|---|---|
| url | string | Required Blog index / RSS / sitemap URL |
| limit | int | Default: 10 Max posts to scan |
| content_type | string | Default: blog |
/api/v1/builder/researchGate 1: research keyword + N tools. LLM does web search + per-tool lookup.
| Field | Type | Notes |
|---|---|---|
| primary_keyword | string | Required |
| audience | string | Required e.g. 'B2B event teams' |
| tool_count | int | Default: 6 2-15 |
| house_product | string | Required Your brand to lead with |
| llm_provider | string | Default: auto auto | claude | gpt | mock |
| mock | bool | Default: false Use fixtures, no LLM |
/api/v1/builder/generateGate 2: write the draft. Returns draft_md + QA report + editorial score.
| Field | Type | Notes |
|---|---|---|
| research_bundle | object | Required Output of /builder/research |
| format | string | Default: listicle listicle | comparison | alternatives | buyers_guide |
| llm_provider | string | Default: auto |
| mock | bool | Default: false |
/api/v1/billing/entitlementCurrent tenant + tier + credit balance + usage this period.
/api/v1/checkout/create-sessionCreate a Razorpay (or Stripe) checkout session for a paid tier. Requires a signed-in session (Bearer JWT).
| Field | Type | Notes |
|---|---|---|
| tier | string | Required growth | pro | scale |
| cycle | string | Default: monthly monthly | annual |
/api/v1/catalog/enginesList the supported engines (SEO/AEO/GEO) and their check names.
/api/v1/admin_ext/auto_fixOne-click AI rewrite for a failed check (GLM 5.2). Requires a Growth+ plan; consumes from the rewrite allowance, never from scans.
| Field | Type | Notes |
|---|---|---|
| content | string | Required The post body |
| check_name | string | Required The failing check |
| reasons | string[] | Optional From check.reasons[] |
| metrics | object | Optional From check.metrics{} |
/openapi.jsonFull OpenAPI 3.1 spec. Use `dokeo openapi --out spec.json` to dump.
Errors
| Code | Meaning |
|---|---|
| 401 | Missing or invalid Bearer token |
| 402 | Out of credits. Upgrade or wait for refill. |
| 404 | Path or scan result not found. |
| 422 | Validation error (missing field, wrong content type). |
| 429 | Rate limit exceeded. Check X-RateLimit-Reset header. |
| 502 | Upstream (Razorpay, search providers) unavailable. |
| 503 | Server missing required configuration. |