API reference
SEO toolkit
Standalone endpoints that help any website rank, plain HTML included, with no connected WordPress site required. Audit a page, research keywords, write articles, metadata and headings, generate structured data, robots.txt and sitemaps, rewrite copy and preview Google results. The AI-powered endpoints use the account's monthly AI-call allowance; the computed ones are free. Results are saved to your account unless you send save: false: browse them in Dashboard → SEO Lab or with GET /seo/analyses.
15 endpointsBase URL https://autoranko.com/api/public/v1Every request needs a bearer token
Audit a page
https://autoranko.com/api/public/v1/seo/analyzeFetches any public page, from a CMS page to a hand-written HTML file, and audits it for search in four layers. page holds the facts parsed from the HTML: title, meta description, canonical, robots, headings, word count, images, links, Open Graph, JSON-LD and hreflang. heuristics is a rule-based audit scored out of 100. serp_preview shows how the current title and description render on Google. expert is a senior consultant's review, written by AI.
The rule-based layers are deterministic: the same page always gets the same score, issues and checks, so you can track them over time, and their notes are in English. The expert review adds what rules can't judge, such as search intent, persuasiveness and the biggest blocker, with prioritized recommendations in the page's language.
Request
application/jsonurlstring (uri)RequiredThe page to audit. Any publichttporhttpsURL; a bare host such asgladiacteur.comgetshttps://added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.- Max length
2048 characters- Example
https://gladiacteur.com
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/analyze \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://gladiacteur.com"
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/analyze", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://gladiacteur.com",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
console.log(`Score ${data.heuristics.score}/100: ${data.expert.verdict}`);
for (const issue of data.heuristics.issues) console.log(issue.severity, issue.problem);import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/analyze",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"url": "https://gladiacteur.com",
},
timeout=130,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
print(f"Score {data['heuristics']['score']}/100: {data['expert']['verdict']}")
for issue in data["heuristics"]["issues"]:
print(issue["severity"], issue["problem"])<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/analyze');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 130,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'url' => 'https://gladiacteur.com',
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
printf("Score %d/100: %s\n", $data['heuristics']['score'], $data['expert']['verdict']);
foreach ($data['heuristics']['issues'] as $issue) echo $issue['severity'], ' ', $issue['problem'], "\n";Response
200OKThe page facts, the scored audit, the SERP preview and the expert review.
application/jsonpageobjectWhat the parser found on the page.pagekeys(27)SeoPageurlstring (uri)The URL as requested, normalized (https://added to a bare host).final_urlstring (uri)The URL the page was read from, after redirects (at most 3 are followed).http_statusintegerHTTP status of the final response. Always below 400: an error page gets 422 fetch_failed instead.httpsbooleantruewhenfinal_urluses HTTPS.titlestring or nullText of the<title>tag, ornullif the page has none.title_lengthintegerCharacters intitle(0 without one).meta_descriptionstring or nullContent of the meta description tag, ornullif the page has none.meta_description_lengthintegerCharacters inmeta_description(0 without one).canonicalstring or nullTherel=canonicalURL as written in the HTML (it can be relative), ornull.robots_metastring or nullContent of the robots meta tag, such asindex, follow, ornull.langstring or nullThe<html lang>attribute, such asfr-FR, ornull.viewportbooleanWhether the page has a viewport meta tag.charsetbooleanWhether the page declares its character set in a meta tag.faviconbooleanWhether the page declares a favicon.h1array of stringsText of the<h1>headings, in page order (at most 25).h2array of stringsText of the<h2>headings, in page order (at most 25).h3array of stringsText of the<h3>headings, in page order (at most 25).word_countintegerWords of visible text, leaving out scripts, styles,<nav>and<footer>.images_totalintegerNumber of<img>tags.images_missing_altinteger<img>tags whose alt text is missing or empty (decorative images withalt=""included).links_internalintegerLinks to the page's own host (www.ignored).links_externalintegerLinks to other hosts.open_graphobjectEveryog:*meta tag, keyed by property, such asog:title.twitter_cardobjectEverytwitter:*meta tag, keyed by name, such astwitter:card.json_ld_typesarray of stringsThe@typevalues in the page's JSON-LD,@graphnodes included, without duplicates.(unparseable JSON-LD)marks a block that isn't valid JSON.hreflangarray of objectsThe page'shreflangalternate links.hreflangitems(2)langstringThehreflangvalue, such asfrorx-default.hrefstringThe alternate URL, as written.
html_size_bytesintegerSize of the HTML in characters, as read (the fetch stops at 5 MB).
heuristicsobjectThe rule-based audit.heuristicskeys(2)scoreintegerOn-page score from 0 to 100: 100 minus 18 per critical, 10 per major and 4 per minor issue, never below 0.issuesarray of objectsEvery problem found, most severe first. An empty list means the page passed every rule.issuesitems(4)SeoIssueseveritystringHow much the issue costs:criticaltakes 18 points offscore,major10 andminor4.One of
criticalmajorminorelementstringWhat the issue is about, such astitle,h1,canonical,imagesoropen graph.problemstringWhat's wrong, in English.fixstringHow to fix it, in English.
serp_previewobjectThe page's current title and meta description as Google renders them: the same output as POST /seo/serp-preview without akeyword.serp_previewkeys(3)SerpPreviewpreviewobjectThe result as searchers would see it on desktop.previewkeys(3)title_shownstringThe title as displayed: cut at a word boundary, with...added, when it's wider than about 580px.description_shownstringThe description as displayed, cut the same way after about 920px (two lines).breadcrumbstringThe URL line under the site name: the host, then up to 3 path segments, separated by›.
measurementsobjectLengths and rendered widths. Widths are approximate pixels, computed from Arial's font metrics.measurementskeys(3)titleobjectThe title, at the size of a desktop result title.titlekeys(5)charsintegerLength in characters.pixelsintegerRendered width in pixels.limit_pixelsintegerGoogle's desktop limit for titles: 580.truncatedbooleantruewhen Google would cut it.fontstringThe font the widths assume:20px Arial (approx.).
descriptionobjectThe meta description, at the size of a result snippet.descriptionkeys(7)charsintegerLength in characters.pixelsintegerRendered width in pixels, on one line.limit_pixelsintegerGoogle's desktop limit, two lines: 920.mobile_limit_pixelsintegerGoogle's mobile limit: 680.truncatedbooleantruewhen Google would cut it on desktop.fits_mobilebooleantruewhen it fits on mobile too.fontstringThe font the widths assume:14px Arial (approx.).
urlobjectThe URL.urlkeys(3)charsintegerLength in characters.path_depthinteger or nullNumber of path segments (/blog/post/is 2), ornullif the URL can't be parsed.httpsboolean or nulltruefor an HTTPS URL, ornullif the URL can't be parsed.
checksarray of objectsTen pass/fail checks, in this order:title_length,title_width,description_length,description_width,keyword_placement,url_readable,https,title_case(not mostly uppercase),title_repetition(no keyword stuffing) andtitle_vs_description(the description adds to the title).keyword_placementis exact when a keyword is given; otherwise it's informational, comparing the title's lead words with the description.checksitems(3)SeoCheckcheckstringMachine-readable name of the check, such astitle_widthorsitemap_vs_robots.passbooleantruewhen the check passes.notestringWhat was measured or found and, on a failure, what to do about it. Always in English.
expertobjectThe consultant's review, written by AI in the page's language. A value the model didn't provide isnull.expertkeys(8)verdictstring or nullThe overall verdict, in 2–3 sentences.intent_analysisstring or nullWhat searchers want from this page's topic, and whether the content delivers it.strongest_assetstring or nullWhat the page already does well.biggest_blockerstring or nullThe one thing holding the page back the most.recommendationsarray of objectsPrioritized actions, usually 5–8, most important first.recommendationsitems(4)prioritystring or nullHow much it matters.One of
highmediumlowactionstringWhat to do.whystringWhy it matters (can be empty).effortstring or nullRough effort it takes.One of
minuteshoursdays
suggested_target_keywordstring or nullThe query the page should target.suggested_titlestring or nullA better title, aimed at 60 characters or less.suggested_meta_descriptionstring or nullA better meta description, aimed at 160 characters or less.
analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/analyzeIllustrative
{
"url": "https://gladiacteur.com"
}{
"page": {
"url": "https://gladiacteur.com/",
"final_url": "https://gladiacteur.com/",
"http_status": 200,
"https": true,
"title": "Gladiacteur - IA, Technologie et Business : Outils, Tendances & Transformation Digitale",
"title_length": 87,
"meta_description": "Découvrez comment l’IA, les technologies et l’automatisation transforment les entreprises. Tendances, outils, transformation digitale et stratégies business pour améliorer votre croissance.",
"meta_description_length": 189,
"canonical": "https://gladiacteur.com/",
"robots_meta": "follow, index",
"lang": "fr-FR",
"viewport": true,
"charset": true,
"favicon": true,
"h1": [],
"h2": [],
"h3": [
"8 Prompts ChatGPT pour votre Business Plan",
"Outils pour Manager : Suite Complète d’Outils de Gestion Stratégique Gratuits"
],
"word_count": 444,
"images_total": 28,
"images_missing_alt": 6,
"links_internal": 77,
"links_external": 5,
"open_graph": {
"og:locale": "fr_FR",
"og:type": "website",
"og:title": "Gladiacteur",
"og:description": "L'intelligence artificielle peut transformer votre entreprise : automatisation, analyse de données et optimisation des performances.",
"og:url": "https://gladiacteur.com/",
"og:site_name": "Gladiacteur"
},
"twitter_card": {
"twitter:card": "summary_large_image",
"twitter:title": "Gladiacteur",
"twitter:description": "L'intelligence artificielle peut transformer votre entreprise : automatisation, analyse de données et optimisation des performances."
},
"json_ld_types": [
"Person",
"WebSite",
"CollectionPage"
],
"hreflang": [],
"html_size_bytes": 114615
},
"heuristics": {
"score": 70,
"issues": [
{
"severity": "major",
"element": "h1",
"problem": "No <h1> heading.",
"fix": "Add exactly one <h1> stating the page's topic with the primary keyword."
},
{
"severity": "minor",
"element": "title",
"problem": "Title is 87 chars; Google truncates around 60.",
"fix": "Front-load the keyword and trim to ≤60 characters."
},
{
"severity": "minor",
"element": "open graph",
"problem": "Open Graph tags have no og:image, so shares render without a picture.",
"fix": "Add og:image: an absolute URL to a 1200x630 image under 5 MB."
}
]
},
"serp_preview": {
"preview": {
"title_shown": "Gladiacteur - IA, Technologie et Business : Outils, Tendances ...",
"description_shown": "Découvrez comment l’IA, les technologies et l’automatisation transforment les entreprises. Tendances, outils, transformation digitale et stratégies ...",
"breadcrumb": "gladiacteur.com"
},
"measurements": {
"title": {
"chars": 87,
"pixels": 777,
"limit_pixels": 580,
"truncated": true,
"font": "20px Arial (approx.)"
},
"description": {
"chars": 189,
"pixels": 1160,
"limit_pixels": 920,
"mobile_limit_pixels": 680,
"truncated": true,
"fits_mobile": false,
"font": "14px Arial (approx.)"
},
"url": {
"chars": 24,
"path_depth": 0,
"https": true
}
},
"checks": [
{
"check": "title_width",
"pass": false,
"note": "About 777px wide, over the ~580px desktop limit. Searchers will see: \"Gladiacteur - IA, Technologie et Business : Outils, Tendances ...\""
},
{
"check": "description_width",
"pass": false,
"note": "About 1160px: cut after ~920px (two desktop lines). On mobile (~680px) it will be cut, so put the key promise first."
},
{
"check": "https",
"pass": true,
"note": "Served over HTTPS."
}
]
},
"expert": {
"verdict": "La page d'accueil est un bon hub éditorial (77 liens internes, 13 articles mis en avant), mais elle ne cible aucune requête : ni <h1> ni <h2>, et un title de 87 caractères coupé dans Google. En l'état, elle ne peut se classer que sur la marque.",
"intent_analysis": "Les requêtes visées (IA en entreprise, outils IA, transformation digitale) sont informationnelles. La page y répond par une liste d'articles sans texte de synthèse : elle aide à naviguer, pas à comprendre le sujet.",
"strongest_asset": "Le maillage interne vers des articles approfondis sur l'IA en entreprise, avec des données structurées WebSite et CollectionPage déjà en place.",
"biggest_blocker": "L'absence de <h1> et de texte d'introduction : Google ne sait pas sur quel sujet classer la page.",
"recommendations": [
{
"priority": "high",
"action": "Ajouter un <h1> unique, par exemple « L'IA au service des entreprises », suivi de 150 à 200 mots d'introduction.",
"why": "Donne à Google le sujet principal de la page et répond à l'intention dès le haut de page.",
"effort": "hours"
},
{
"priority": "high",
"action": "Raccourcir le title à 60 caractères au plus, mot-clé en tête.",
"why": "À 87 caractères, Google coupe « Transformation Digitale », la partie la plus recherchée.",
"effort": "minutes"
}
],
"suggested_target_keyword": "IA en entreprise",
"suggested_title": "IA en entreprise : outils et stratégies | Gladiacteur",
"suggested_meta_description": "Outils IA, automatisation et stratégies concrètes : Gladiacteur aide les entreprises à réussir leur transformation digitale et à accélérer leur croissance."
},
"analysis_id": "128"
}page, heuristics and serp_preview were computed by the endpoint's own code from the live gladiacteur.com homepage; expert is illustrative. Lists are shortened: the audit found 6 issues.
POST/seo/analyzeIllustrative
{
"url": "https://gladiacteur.com/page-introuvable"
}{
"error": {
"code": "fetch_failed",
"message": "https://gladiacteur.com/page-introuvable/ answered HTTP 404. Check the URL."
}
}The URL redirects to its trailing-slash form, which answers 404, so message names the final URL.
Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | url is missing (url is required.) or isn't a public http or https URL with a domain name. |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 422fetch_failed | The page at url can't be fetched: the domain doesn't resolve, the server doesn't answer within 15 seconds, the host is private, or the page answers with a status of 400 or more. message names the URL and the reason. |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
| 429plan_limit | The account's monthly AI-call allowance can't cover the call this request needs (Monthly AI call allowance reached (300/300 on the free plan). Upgrade at https://autoranko.com/pricing or wait for next month.). It's checked before the body is read. |
| 502upstream_error | The AI request failed (The AI request failed, please retry.) or its result was unusable (The AI returned an incomplete result, please retry.). |
Research keywords for any site
https://autoranko.com/api/public/v1/seo/keywordsKeyword research without a connected site. The seeds come from keywords, then topic, then the page at url (its title segments and headings, at most 5 phrases), up to 20 in all; seeds_used shows exactly which were sent. In ideas mode (the default) the AI expands them into related long-tail keywords, a mix of informational and commercial searches. In metrics mode it estimates metrics for the seeds themselves.
Each keyword comes with estimated monthly volume, competition, difficulty and cost per click. All numbers are AI estimates (estimated is always true): good for comparing and prioritizing keywords, not exact traffic data. A metric the model didn't return is absent. Use language and country to target a market.
Request
application/jsontopicstringOptionalWhat you want to rank for, as a phrase. Send at least one oftopic,urlandkeywords.- Length
2–300 characters- Example
outils IA pour PME
urlstring (uri)OptionalA page to take seed phrases from: its title segments, then its headings, skipping the brand name and generic headings such asContact. Any publichttporhttpsURL; a bare host such asgladiacteur.comgetshttps://added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.- Max length
2048 characters- Example
https://gladiacteur.com
keywordsarray of stringsOptionalSeed keywords (ideas) or the exact keywords to evaluate (metrics): a JSON array of 1–20 non-empty strings, each up to 100 characters.- Max items
20- Example
["outils IA","automatisation PME"]
modestringOptionalideasexpands the seeds into related keywords;metricsestimates metrics for the seeds themselves, including the ones taken fromtopicandurl.One of
ideasmetrics- Default
ideas- Example
ideas
languagestringOptionalLanguage of the keywords. Defaults to the page'slangwhenurlis sent. Send a language name or code, such asfr,fr-FRorFrench.- Length
2–40 characters- Example
fr
countrystringOptionalThe market to estimate for: a country name or code, such asFRorFrance.- Max length
60 characters- Example
FR
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/keywords \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"topic": "outils IA pour PME",
"language": "fr",
"country": "FR"
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/keywords", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
topic: "outils IA pour PME",
language: "fr",
country: "FR",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
for (const k of data.keywords) {
console.log(`${k.keyword}: volume ${k.volume}, difficulty ${k.difficulty}`);
}import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/keywords",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"topic": "outils IA pour PME",
"language": "fr",
"country": "FR",
},
timeout=130,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
for k in data["keywords"]:
print(f"{k['keyword']}: volume {k.get('volume')}, difficulty {k.get('difficulty')}")<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/keywords');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 130,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'topic' => 'outils IA pour PME',
'language' => 'fr',
'country' => 'FR',
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
foreach ($data['keywords'] as $k) printf("%s: volume %d, difficulty %d\n", $k['keyword'], $k['volume'] ?? 0, $k['difficulty'] ?? 0);Response
200OKKeywords with AI-estimated metrics.
application/jsonmodestringThe mode that ran.One of
ideasmetricskeywordsarray of objectsKeywords with estimated metrics, without duplicates. A metric the model didn't return is absent.keywordsitems(6)KeywordkeywordstringThe keyword.volumeintegerOptionalEstimated monthly searches.competitionstringOptionalEstimated advertiser competition.One of
LOWMEDIUMHIGHcompetition_indexintegerOptionalCompetition on a 0–100 scale.difficultyintegerOptionalEstimated difficulty of ranking on page one, 0–100.cpcnumberOptionalEstimated cost per click, in USD.
estimatedbooleanAlwaystrue: every metric is an AI estimate.seeds_usedarray of stringsThe seed phrases sent to the AI, at most 20:keywordsfirst, thentopic, then phrases from the page aturl.analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/keywordsIllustrative
{
"topic": "outils IA pour PME",
"language": "fr",
"country": "FR"
}{
"mode": "ideas",
"keywords": [
{
"keyword": "outils ia pour pme",
"volume": 880,
"competition": "MEDIUM",
"competition_index": 54,
"difficulty": 38,
"cpc": 2.4
},
{
"keyword": "meilleur outil ia gratuit entreprise",
"volume": 590,
"competition": "MEDIUM",
"competition_index": 47,
"difficulty": 35,
"cpc": 1.85
},
{
"keyword": "logiciel ia gestion pme",
"volume": 320,
"competition": "HIGH",
"competition_index": 71,
"difficulty": 44,
"cpc": 4.6
},
{
"keyword": "automatiser sa pme avec l'ia",
"volume": 210,
"competition": "LOW",
"competition_index": 28,
"difficulty": 22,
"cpc": 2.1
}
],
"estimated": true,
"seeds_used": [
"outils IA pour PME"
],
"analysis_id": "129"
}The keywords and their metrics are illustrative AI estimates.
POST/seo/keywordsIllustrative
{
"mode": "metrics"
}{
"error": {
"code": "invalid_body",
"message": "Send at least one of topic, url or keywords."
}
}Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | None of topic, url and keywords was sent (Send at least one of topic, url or keywords.). |
| 400invalid_body | A field has the wrong type or is out of bounds (length, range, item count or format); message names it (keywords accepts at most 20 items.). |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 422fetch_failed | url was sent, and the page can't be fetched: the domain doesn't resolve, the server doesn't answer within 15 seconds, the host is private, or the page answers with a status of 400 or more. message names the URL and the reason. |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
| 429plan_limit | The account's monthly AI-call allowance can't cover the call this request needs (Monthly AI call allowance reached (300/300 on the free plan). Upgrade at https://autoranko.com/pricing or wait for next month.). It's checked before the body is read. |
| 502upstream_error | The AI request failed (The AI request failed, please retry.) or its result was unusable (The AI returned an incomplete result, please retry. or The AI returned no keywords, please retry.). |
Write a long-form article
https://autoranko.com/api/public/v1/seo/articleWrites a complete SEO article without a connected site, in two AI steps: an outline (title, meta description, slug, sections and FAQs), then the full HTML body written from it. Ask for 500–4,000 words (1,600 by default) in the tone and language you need. Tables are used where data helps; no images are added.
The call is synchronous and typically takes 1–3 minutes. The response has everything needed to publish anywhere: title, meta_description, slug and html, plus the outline it was written from. word_count is counted from the HTML, not taken from the model.
Request
application/jsontopicstringRequiredWhat the article should be about: a working title, a question or a short brief.- Length
3–300 characters- Example
Comment automatiser sa prospection B2B avec l'IA en 2026
target_keywordstringOptionalThe search query the article should rank for. Without one, the outline picks it.- Max length
120 characters- Example
automatiser prospection B2B IA
word_countintegerOptionalTarget length in words. The result lands close to it rather than exactly on it.- Default
1600- Range
500–4000- Example
1500
tonestringOptionalThe voice to write in, in your own words, such asfriendly, practicalorformal, expert.- Default
professional, helpful- Max length
120 characters- Example
professional, helpful
languagestringOptionalLanguage to write in. Without it, the AI usually follows the language oftopic. Send a language name or code, such asfr,fr-FRorFrench.- Length
2–40 characters- Example
fr
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/article \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"topic": "Comment automatiser sa prospection B2B avec l'\''IA en 2026",
"target_keyword": "automatiser prospection B2B IA",
"word_count": 1500,
"language": "fr"
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/article", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
topic: "Comment automatiser sa prospection B2B avec l'IA en 2026",
target_keyword: "automatiser prospection B2B IA",
word_count: 1500,
language: "fr",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
console.log(`${data.title} (${data.word_count} words, ${data.reading_time_minutes} min read)`);
console.log(data.html.slice(0, 300));import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/article",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"topic": "Comment automatiser sa prospection B2B avec l'IA en 2026",
"target_keyword": "automatiser prospection B2B IA",
"word_count": 1500,
"language": "fr",
},
timeout=310,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
print(f"{data['title']} ({data['word_count']} words, {data['reading_time_minutes']} min read)")
print(data["html"][:300])<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/article');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 310,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'topic' => 'Comment automatiser sa prospection B2B avec l\'IA en 2026',
'target_keyword' => 'automatiser prospection B2B IA',
'word_count' => 1500,
'language' => 'fr',
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
printf("%s (%d words)\n%s\n", $data['title'], $data['word_count'], substr($data['html'], 0, 300));Response
200OKThe finished article, with its metadata and outline.
application/jsontitlestringThe article title, from the outline (topicif the outline has none).meta_descriptionstring or nullSEO meta description (requested under 160 characters), ornullif the outline has none.slugstringURL slug: lowercase ASCII words joined by hyphens, accents and French elisions removed (l'IAbecomesia), at most 75 characters.target_keywordstring or nullThe primary keyword: the outline's, else the one you sent;nullif neither.secondary_keywordsarray of stringsRelated keywords the article works in.outlineobjectThe outline the article was written from: the same AI step and structure as a job'soutline. Keys are requested from the model, not guaranteed.outlinekeys(10)JobOutlinetitlestringOptionalArticle title.meta_descriptionstringOptionalSEO meta description.slugstringOptionalSuggested URL slug.target_keywordstringOptionalPrimary keyword.secondary_keywordsarray of stringsOptionalRelated keywords to work into the article.sectionsarray of objectsOptionalThe article structure, in order.sectionsitems(4)levelstringHeading level.One of
h2h3headingstringSection heading.descriptionstringWhat the section covers.word_countintegerPlanned length of the section in words.
faqsarray of objectsOptionalQuestions for the FAQ section.faqsitems(2)questionstringThe question.answer_briefstringThe gist of the answer.
image_suggestionsarray of objectsOptionalImage ideas. The first one is meant as the featured image.image_suggestionsitems(2)descriptionstringWhat the image shows.alt_textstringSuggested alt text.
google_image_queriesarray of stringsOptionalSearch queries for finding matching images.video_querystringOptionalSearch query for a related video.
htmlstringThe article body as HTML: headings start at<h2>(the title is separate), with tables where data helps and no images. Ready to publish undertitle.word_countintegerWords inhtml, counted by Autoranko rather than reported by the model.reading_time_minutesintegerEstimated reading time at 230 words a minute (at least 1).analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/articleIllustrative
{
"topic": "Comment automatiser sa prospection B2B avec l'IA en 2026",
"target_keyword": "automatiser prospection B2B IA",
"word_count": 1500,
"language": "fr"
}{
"title": "Automatiser sa prospection B2B avec l'IA en 2026 : le guide complet",
"meta_description": "Automatisez votre prospection B2B avec l'IA : outils, scénarios et bonnes pratiques RGPD pour décrocher plus de rendez-vous qualifiés en 2026.",
"slug": "automatiser-prospection-b2b-ia",
"target_keyword": "automatiser prospection B2B IA",
"secondary_keywords": [
"prospection B2B automatisée",
"outils IA de prospection",
"séquences d'emails personnalisées"
],
"outline": {
"title": "Automatiser sa prospection B2B avec l'IA en 2026 : le guide complet",
"meta_description": "Automatisez votre prospection B2B avec l'IA : outils, scénarios et bonnes pratiques RGPD pour décrocher plus de rendez-vous qualifiés en 2026.",
"slug": "automatiser-prospection-b2b-ia",
"target_keyword": "automatiser prospection B2B IA",
"secondary_keywords": [
"prospection B2B automatisée",
"outils IA de prospection",
"séquences d'emails personnalisées"
],
"sections": [
{
"level": "h2",
"heading": "Pourquoi automatiser sa prospection B2B en 2026 ?",
"description": "Ce que coûte une prospection manuelle, et ce que l'IA change.",
"word_count": 250
},
{
"level": "h2",
"heading": "Les 5 étapes pour automatiser sa prospection avec l'IA",
"description": "Du ciblage à la relance, avec un outil par étape.",
"word_count": 450
}
],
"faqs": [
{
"question": "L'automatisation de la prospection est-elle compatible avec le RGPD ?",
"answer_brief": "Oui en B2B, avec un intérêt légitime documenté et un lien de désinscription dans chaque message."
}
],
"image_suggestions": [
{
"description": "Commercial devant un tableau de bord de prospection piloté par l'IA",
"alt_text": "Tableau de bord de prospection B2B automatisée par l'IA"
}
],
"google_image_queries": [
"prospection B2B intelligence artificielle"
],
"video_query": "automatiser sa prospection B2B avec l'IA"
},
"html": "<p>Automatiser sa prospection B2B avec l'IA, c'est confier à des outils le ciblage, la personnalisation des messages et les relances, pour que vos commerciaux se concentrent sur les rendez-vous.</p>\n<h2>Pourquoi automatiser sa prospection B2B en 2026 ?</h2>\n<p>Une prospection manuelle repose sur des tâches répétitives : trouver les bons contacts, personnaliser chaque message, relancer au bon moment.</p>\n<!-- … shortened for the docs … -->",
"word_count": 1563,
"reading_time_minutes": 7,
"analysis_id": "141"
}html is shortened, and outline is abbreviated to show its structure.
POST/seo/articleIllustrative
{
"topic": "Comment automatiser sa prospection B2B avec l'IA en 2026",
"target_keyword": "automatiser prospection B2B IA",
"word_count": 1500,
"language": "fr"
}{
"error": {
"code": "plan_limit",
"message": "Monthly AI call allowance reached (1499/1500 on the starter plan; this endpoint needs 2 calls). Upgrade at https://autoranko.com/pricing or wait for next month."
}
}One AI call was left this month, and the endpoint needs two.
Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | topic is missing or blank (topic is required.). |
| 400invalid_body | A field has the wrong type or is out of bounds (length, range, item count or format); message names it (word_count must be between 500 and 4000.). |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
| 429plan_limit | The account's monthly AI-call allowance can't cover the two calls this request needs (Monthly AI call allowance reached (1499/1500 on the starter plan; this endpoint needs 2 calls). Upgrade at https://autoranko.com/pricing or wait for next month.). It's checked before the body is read. |
| 502upstream_error | The AI request failed (The AI request failed, please retry.) or its result was unusable (The AI returned an incomplete result, please retry. or The AI returned an incomplete outline, please retry. or The AI returned a truncated article, please retry.). |
Write a short article
https://autoranko.com/api/public/v1/seo/article-shortWrites a short, publication-ready piece of 150–800 words (400 by default): a news post, a product blurb, an FAQ answer or a landing-page section. It answers the query in its first two sentences, then backs the answer up with one or two <h2> sections at most, and a list or small table where it genuinely helps.
html has no <h1> (the title is separate) and no images, ready to drop into a page under title. word_count is counted from the HTML, not taken from the model.
Request
application/jsontopicstringRequiredWhat the piece should answer or cover: a question, a working title or a short brief.- Length
3–300 characters- Example
Les 5 erreurs à éviter quand on adopte l'IA en PME
target_keywordstringOptionalThe search query the piece should rank for.- Max length
120 characters- Example
adopter IA PME
word_countintegerOptionalTarget length in words. The result lands close to it rather than exactly on it.- Default
400- Range
150–800- Example
400
tonestringOptionalThe voice to write in, in your own words, such asfriendly, practicalorformal, expert.- Default
clear, expert, helpful- Max length
120 characters- Example
clear, expert, helpful
languagestringOptionalLanguage to write in. Without it, the AI usually follows the language oftopic. Send a language name or code, such asfr,fr-FRorFrench.- Length
2–40 characters- Example
fr
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/article-short \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"topic": "Les 5 erreurs à éviter quand on adopte l'\''IA en PME",
"target_keyword": "adopter IA PME",
"word_count": 400,
"language": "fr"
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/article-short", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
topic: "Les 5 erreurs à éviter quand on adopte l'IA en PME",
target_keyword: "adopter IA PME",
word_count: 400,
language: "fr",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
console.log(data.title, `(${data.word_count} words)`);
console.log(data.html);import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/article-short",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"topic": "Les 5 erreurs à éviter quand on adopte l'IA en PME",
"target_keyword": "adopter IA PME",
"word_count": 400,
"language": "fr",
},
timeout=130,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
print(data["title"], f"({data['word_count']} words)")
print(data["html"])<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/article-short');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 130,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'topic' => 'Les 5 erreurs à éviter quand on adopte l\'IA en PME',
'target_keyword' => 'adopter IA PME',
'word_count' => 400,
'language' => 'fr',
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
printf("%s (%d words)\n%s\n", $data['title'], $data['word_count'], $data['html']);Response
200OKThe finished piece and its metadata.
application/jsontitlestringThe title (topicif the model returned none).meta_descriptionstring or nullSEO meta description (requested at 160 characters or less), ornull.slugstringURL slug: lowercase ASCII words joined by hyphens, at most 75 characters.htmlstringThe body as HTML, with no<h1>and no images.word_countintegerWords inhtml, counted by Autoranko rather than reported by the model.analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/article-shortIllustrative
{
"topic": "Les 5 erreurs à éviter quand on adopte l'IA en PME",
"target_keyword": "adopter IA PME",
"word_count": 400,
"language": "fr"
}{
"title": "Adopter l'IA en PME : les 5 erreurs à éviter",
"meta_description": "Adopter l'IA en PME sans faux pas : objectifs flous, données négligées, équipes oubliées. Les 5 erreurs à éviter et comment les corriger.",
"slug": "adopter-ia-pme-erreurs-a-eviter",
"html": "<p>Pour adopter l'IA en PME, partez d'un problème métier précis et mesurable, pas de l'outil à la mode. La plupart des échecs viennent de cinq erreurs évitables.</p>\n<h2>Les 5 erreurs les plus fréquentes</h2>\n<ol>\n<li><strong>Commencer par l'outil</strong> plutôt que par le besoin.</li>\n<!-- … shortened for the docs … -->",
"word_count": 412,
"analysis_id": "135"
}html is shortened.
POST/seo/article-shortIllustrative
{
"topic": "Les 5 erreurs à éviter quand on adopte l'IA en PME",
"word_count": 1200
}{
"error": {
"code": "invalid_body",
"message": "word_count must be between 150 and 800."
}
}Ask POST /seo/article for anything over 800 words.
Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | topic is missing or blank (topic is required.). |
| 400invalid_body | A field has the wrong type or is out of bounds (length, range, item count or format); message names it (word_count must be between 150 and 800.). |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
| 429plan_limit | The account's monthly AI-call allowance can't cover the call this request needs (Monthly AI call allowance reached (300/300 on the free plan). Upgrade at https://autoranko.com/pricing or wait for next month.). It's checked before the body is read. |
| 502upstream_error | The AI request failed (The AI request failed, please retry.) or its result was unusable (The AI returned an incomplete result, please retry. or The AI returned a truncated article, please retry.). |
Generate Open Graph and Twitter tags
https://autoranko.com/api/public/v1/seo/open-graphGenerates a page's social-sharing tags: every Open Graph tag (og:title, og:description, og:type, og:url, og:site_name, og:image, og:image:alt and og:locale) and the Twitter card, plus a ready-to-paste block of <meta> tags.
Facts beat the model: og:url is the page's canonical URL, and og:image only ever comes from image_url or the page's existing og:image, never invented. Whatever stays empty is listed in missing, and image_brief describes the 1200×630 image to create when there's none.
Request
application/jsonurlstring (uri)OptionalThe page to tag: its title, description, canonical and existing social tags are used. Any publichttporhttpsURL; a bare host such asgladiacteur.comgetshttps://added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.- Max length
2048 characters- Example
https://gladiacteur.com
topicstringOptionalWhat a new page is about, when there's nourl. Sendurl,topicor both.- Length
2–300 characters- Example
transformation digitale des PME
brandstringOptionalYour brand name. It becomesog:site_name, overriding the model and the page.- Max length
80 characters- Example
Gladiacteur
image_urlstring (uri)OptionalThe share image, ideally 1200×630: an absolutehttporhttpsURL, used as is (it isn't fetched). Without it, the page's existingog:imageis kept; none is ever invented.- Max length
2048 characters- Example
https://gladiacteur.com/images/partage-ia.png
languagestringOptionalLanguage of the tags. Defaults to the page'slangwhenurlis sent. Send a language name or code, such asfr,fr-FRorFrench.- Length
2–40 characters- Example
fr
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/open-graph \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://gladiacteur.com"
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/open-graph", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://gladiacteur.com",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
console.log(data.html);
if (data.missing.length) console.log("Missing:", data.missing.join(", "), "-", data.image_brief);import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/open-graph",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"url": "https://gladiacteur.com",
},
timeout=130,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
print(data["html"])
if data["missing"]:
print("Missing:", ", ".join(data["missing"]), "-", data["image_brief"])<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/open-graph');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 130,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'url' => 'https://gladiacteur.com',
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
echo $data['html'], "\n";
if ($data['missing']) echo 'Missing: ', implode(', ', $data['missing']), ' - ', $data['image_brief'], "\n";Response
200OKThe final tags, the ready-to-paste block and what's still missing.
application/jsonogobjectThe Open Graph tags. Every key is always present; one that couldn't be filled is an empty string.ogkeys(8)og:titlestringShare title, aimed at 70 characters or less; falls back to the page title ortopic.og:descriptionstringShare description, aimed at 200 characters or less; falls back to the page's meta description.og:typestringThe object type; anything unrecognized becomeswebsite.One of
websitearticleproductprofilebookvideo.movievideo.othermusic.songbusiness.businessog:urlstringThe page's canonical URL, or its final URL when it has no valid canonical. Empty withouturl.og:site_namestringbrandif sent, else the model's value, else the page's existing one.og:imagestringimage_urlif sent, else the page's existingog:imagemade absolute. Never invented: empty when neither exists.og:image:altstringAlt text for the share image.og:localestringSuch asfr_FR: the model's value when it's well-formed, else derived from the page'slang.
twitterobjectThe Twitter (X) card tags.twitterkeys(3)twitter:cardstringThe card type:summary_large_imageunless the model chosesummary.One of
summary_large_imagesummarytwitter:titlestringCard title; falls back toog:title.twitter:descriptionstringCard description; falls back toog:description.
htmlstringThe ready-to-paste block: one<meta>tag per non-empty value ofogandtwitter, HTML-escaped (og:image:altonly with anog:image).missingarray of stringsKeys ofogthat are still empty, such asog:imagewhen neitherimage_urlnor the page provides one.image_briefstring or nullOne sentence describing the ideal 1200×630 share image to create, ornull.currentobject or nullWithurl: the page's existing tags, for comparison.nullwithouturl.currentkeys(2)open_graphobjectEveryog:*meta tag on the page, keyed by property.twitterobjectEverytwitter:*meta tag on the page, keyed by name.
analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/open-graphIllustrative
{
"url": "https://gladiacteur.com"
}{
"og": {
"og:title": "Gladiacteur : l'IA au service de votre entreprise",
"og:description": "Outils IA, automatisation et stratégies concrètes pour réussir la transformation digitale de votre entreprise.",
"og:type": "website",
"og:url": "https://gladiacteur.com/",
"og:site_name": "Gladiacteur",
"og:image": "",
"og:image:alt": "Tableau de bord d'IA illustrant la transformation digitale d'une entreprise",
"og:locale": "fr_FR"
},
"twitter": {
"twitter:card": "summary_large_image",
"twitter:title": "Gladiacteur : l'IA au service de votre entreprise",
"twitter:description": "Outils IA, automatisation et stratégies pour la transformation digitale."
},
"html": "<meta property=\"og:title\" content=\"Gladiacteur : l'IA au service de votre entreprise\">\n<meta property=\"og:description\" content=\"Outils IA, automatisation et stratégies concrètes pour réussir la transformation digitale de votre entreprise.\">\n<meta property=\"og:type\" content=\"website\">\n<meta property=\"og:url\" content=\"https://gladiacteur.com/\">\n<meta property=\"og:site_name\" content=\"Gladiacteur\">\n<meta property=\"og:locale\" content=\"fr_FR\">\n<meta name=\"twitter:card\" content=\"summary_large_image\">\n<meta name=\"twitter:title\" content=\"Gladiacteur : l'IA au service de votre entreprise\">\n<meta name=\"twitter:description\" content=\"Outils IA, automatisation et stratégies pour la transformation digitale.\">",
"missing": [
"og:image"
],
"image_brief": "Un visuel 1200×630 : un tableau de bord d'IA stylisé sur fond bleu nuit, le logo Gladiacteur en bas à droite, sans texte superflu.",
"current": {
"open_graph": {
"og:locale": "fr_FR",
"og:type": "website",
"og:title": "Gladiacteur",
"og:description": "L'intelligence artificielle peut transformer votre entreprise : automatisation, analyse de données et optimisation des performances.",
"og:url": "https://gladiacteur.com/",
"og:site_name": "Gladiacteur"
},
"twitter": {
"twitter:card": "summary_large_image",
"twitter:title": "Gladiacteur",
"twitter:description": "L'intelligence artificielle peut transformer votre entreprise : automatisation, analyse de données et optimisation des performances."
}
},
"analysis_id": "131"
}The page has no share image, so og:image stays empty and is listed in missing. html, missing and current were computed by the endpoint's own code from the model's illustrative values.
POST/seo/open-graphIllustrative
{
"brand": "Gladiacteur"
}{
"error": {
"code": "invalid_body",
"message": "Send url (to tag an existing page) or topic (for a new page)."
}
}Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | Neither url nor topic was sent (Send url (to tag an existing page) or topic (for a new page).). |
| 400invalid_body | A field has the wrong type or is out of bounds (length, range, item count or format); message names it (image_url must be an http(s) URL.). |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 422fetch_failed | url was sent, and the page can't be fetched: the domain doesn't resolve, the server doesn't answer within 15 seconds, the host is private, or the page answers with a status of 400 or more. message names the URL and the reason. |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
| 429plan_limit | The account's monthly AI-call allowance can't cover the call this request needs (Monthly AI call allowance reached (300/300 on the free plan). Upgrade at https://autoranko.com/pricing or wait for next month.). It's checked before the body is read. |
| 502upstream_error | The AI request failed (The AI request failed, please retry.) or its result was unusable (The AI returned an incomplete result, please retry.). |
Generate JSON-LD structured data
https://autoranko.com/api/public/v1/seo/schemaGenerates valid schema.org JSON-LD for one of eight types: article, faq, local_business, product, organization, breadcrumb, howto or website. Pass the facts in details, give a url to read them from the page, or both.
The markup uses only the facts you give. A required fact that's missing becomes a TODO: … string listed in todo_paths, never an invented rating or address. google is a fixed reference of what Google requires and recommends for the type, and whether it still earns a rich result. With url, duplicate_warning flags a type the page already marks up.
Request
application/jsonschema_typestringRequiredThe kind of markup to generate. schema.org names work too, such asLocalBusiness,FAQPage,BlogPosting,NewsArticle,BreadcrumbListorHowTo.One of
articlefaqlocal_businessproductorganizationbreadcrumbhowtowebsite- Max length
40 characters- Example
organization
detailsobjectOptionalThe facts to mark up, as a JSON object of up to 20,000 characters with any keys: names, URLs, address, opening hours, prices, questions and answers. Required unlessurlis sent. Only these facts and the page's are used: a missing required fact becomes aTODO: …string rather than an invention.urlstring (uri)OptionalA page to read facts from as well: its title, description, headings, canonical, Open Graph tags and the JSON-LD types it already has. Any publichttporhttpsURL; a bare host such asgladiacteur.comgetshttps://added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.- Max length
2048 characters- Example
https://gladiacteur.com
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/schema \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"schema_type": "organization",
"url": "https://gladiacteur.com"
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/schema", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
schema_type: "organization",
url: "https://gladiacteur.com",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
console.log(data.html);
if (data.todo_paths.length) console.log("Fill in:", data.todo_paths.join(", "));
if (data.duplicate_warning) console.warn(data.duplicate_warning);import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/schema",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"schema_type": "organization",
"url": "https://gladiacteur.com",
},
timeout=130,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
print(data["html"])
if data["todo_paths"]:
print("Fill in:", ", ".join(data["todo_paths"]))<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/schema');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 130,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'schema_type' => 'organization',
'url' => 'https://gladiacteur.com',
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
echo $data['html'], "\n";
if ($data['todo_paths']) echo 'Fill in: ', implode(', ', $data['todo_paths']), "\n";Response
200OKThe JSON-LD, its <script> block, what's missing and Google's requirements for the type.
application/jsonschema_typestringThe type generated, normalized:local_businessforLocalBusiness, for example.One of
articlefaqlocal_businessproductorganizationbreadcrumbhowtowebsitejson_ldobjectThe JSON-LD, built only fromdetailsand the page, with@contexton every top-level node. A required fact that's missing is aTODO: …string. Usually one object; an array of objects when the markup needs several nodes.htmlstringjson_ldas a ready-to-paste<script type="application/ld+json">block, with<escaped so the block can't be broken out of.missing_fieldsarray of stringsFields Google requires or recommends that the input didn't provide.todo_pathsarray of stringsPaths of theTODO: …placeholders injson_ld, such asaddress.streetAddressorsameAs[0]. Replace them before publishing.validation_notesstring or nullThe model's notes on validity and rich-result eligibility, ornull.googleobjectWhat Google documents for the type: a fixed reference, not generated.googlekeys(4)schema_org_typestringThe schema.org type to use, such asOrganization.google_requiredarray of stringsProperties Google requires.google_recommendedarray of stringsProperties Google recommends.rich_resultstringWhat the markup earns in Google today, including retired rich results (HowTo, and FAQ outside government and health sites).
existing_on_pagearray of strings or nullWithurl: the@typevalues the page already marks up.nullwithouturl.duplicate_warningstring or nullSet when the page already marks up a type this markup generates (often from a CMS or SEO plugin): replace or merge that block rather than adding a second one.nullotherwise.validate_witharray of stringsWhere to test the markup: Google's Rich Results Test and the Schema.org validator.analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/schemaIllustrative
{
"schema_type": "organization",
"details": {
"name": "Gladiacteur",
"url": "https://gladiacteur.com",
"description": "IA, technologie et business: outils et transformation digitale"
}
}{
"schema_type": "organization",
"json_ld": {
"@context": "https://schema.org",
"@type": "Organization",
"name": "Gladiacteur",
"url": "https://gladiacteur.com",
"description": "IA, technologie et business: outils et transformation digitale",
"logo": "TODO: URL of the logo (square, at least 112x112 px)",
"sameAs": [
"TODO: URLs of the official social profiles"
]
},
"html": "<script type=\"application/ld+json\">\n{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"name\": \"Gladiacteur\",\n \"url\": \"https://gladiacteur.com\",\n \"description\": \"IA, technologie et business: outils et transformation digitale\",\n \"logo\": \"TODO: URL of the logo (square, at least 112x112 px)\",\n \"sameAs\": [\n \"TODO: URLs of the official social profiles\"\n ]\n}\n</script>",
"missing_fields": [
"logo",
"sameAs",
"contactPoint"
],
"todo_paths": [
"logo",
"sameAs[0]"
],
"validation_notes": "Valid Organization markup. Fill in logo and sameAs before publishing, and place it on the homepage only.",
"google": {
"schema_org_type": "Organization",
"google_required": [],
"google_recommended": [
"name",
"url",
"logo",
"sameAs",
"contactPoint"
],
"rich_result": "Helps Google's knowledge panel and the logo it shows. Place it on the homepage, with sameAs pointing to your official profiles."
},
"existing_on_page": null,
"duplicate_warning": null,
"validate_with": [
"https://search.google.com/test/rich-results",
"https://validator.schema.org/"
],
"analysis_id": "133"
}The logo and social profiles weren't in details, so they're TODO placeholders. html, todo_paths and google were computed by the endpoint's own code.
POST/seo/schemaIllustrative
{
"schema_type": "recipe",
"details": {
"name": "Gladiacteur"
}
}{
"error": {
"code": "invalid_body",
"message": "schema_type must be one of: article, faq, local_business, product, organization, breadcrumb, howto, website."
}
}Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | schema_type is missing (schema_type is required.) or isn't one of the eight types (schema_type must be one of: article, faq, local_business, product, organization, breadcrumb, howto, website.). |
| 400invalid_body | Neither details nor url was sent (details is required (an object with the facts to mark up), unless url is given to read them from the page.). |
| 400invalid_body | A field has the wrong type or is out of bounds (length, range, item count or format); message names it (details is too large (max 20000 characters of JSON).). |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 422fetch_failed | url was sent, and the page can't be fetched: the domain doesn't resolve, the server doesn't answer within 15 seconds, the host is private, or the page answers with a status of 400 or more. message names the URL and the reason. |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
| 429plan_limit | The account's monthly AI-call allowance can't cover the call this request needs (Monthly AI call allowance reached (300/300 on the free plan). Upgrade at https://autoranko.com/pricing or wait for next month.). It's checked before the body is read. |
| 502upstream_error | The AI request failed (The AI request failed, please retry.) or its result was unusable (The AI returned an incomplete result, please retry. or The AI returned invalid JSON-LD, please retry.). |
Plan the heading structure
https://autoranko.com/api/public/v1/seo/headingsDesigns the heading structure that best serves a query: one <h1>, <h2> sections in search-intent order (the answer first, depth after), <h3> subsections only where a section genuinely splits, and 3–5 questions for an FAQ block.
Send topic for a new page. Send url to restructure an existing one: its current headings are improved rather than replaced blindly, and come back in current for comparison. html lays the structure out as headings, ready to fill in.
Request
application/jsontopicstringOptionalWhat a new page is about. Sendtopic,urlor both.- Length
2–300 characters- Example
outils IA pour entreprise
urlstring (uri)OptionalAn existing page to restructure: its current headings are improved rather than replaced blindly. Any publichttporhttpsURL; a bare host such asgladiacteur.comgetshttps://added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.- Max length
2048 characters- Example
https://gladiacteur.com
target_keywordstringOptionalThe search query the page should rank for.- Max length
120 characters- Example
outils IA pour entreprise
languagestringOptionalLanguage of the headings. Defaults to the page'slangwhenurlis sent. Send a language name or code, such asfr,fr-FRorFrench.- Length
2–40 characters- Example
fr
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/headings \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://gladiacteur.com",
"target_keyword": "outils IA pour entreprise"
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/headings", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://gladiacteur.com",
target_keyword: "outils IA pour entreprise",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
console.log(data.html);
console.log("FAQ:", data.faq_candidates.join(" | "));import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/headings",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"url": "https://gladiacteur.com",
"target_keyword": "outils IA pour entreprise",
},
timeout=130,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
print(data["html"])
print("FAQ:", " | ".join(data["faq_candidates"]))<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/headings');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 130,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'url' => 'https://gladiacteur.com',
'target_keyword' => 'outils IA pour entreprise',
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
echo $data['html'], "\n";
echo 'FAQ: ', implode(' | ', $data['faq_candidates']), "\n";Response
200OKThe recommended headings, as data and as HTML.
application/jsonh1stringThe recommended<h1>.outlinearray of objectsThe<h2>and<h3>structure in reading order: the answer first, depth after.outlineitems(3)levelstringHeading level. The first item is alwaysh2.One of
h2h3headingstringThe heading text.coversstringWhat belongs in the section, in one line (can be empty).
faq_candidatesarray of strings3–5 questions worth answering in an FAQ block.htmlstringh1andoutlineas HTML headings, one per line with<h3>indented, escaped and ready to fill in.currentobject or nullWithurl: the page's current headings (at most 25 per level), for comparison.nullwithouturl.currentkeys(3)h1array of stringsCurrent<h1>headings.h2array of stringsCurrent<h2>headings.h3array of stringsCurrent<h3>headings.
analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/headingsIllustrative
{
"url": "https://gladiacteur.com",
"target_keyword": "outils IA pour entreprise"
}{
"h1": "Outils IA pour entreprise : automatiser, décider, grandir",
"outline": [
{
"level": "h2",
"heading": "Quels outils IA pour votre entreprise en 2026 ?",
"covers": "La réponse directe : les grandes familles d'outils et leur usage."
},
{
"level": "h3",
"heading": "Automatiser les tâches répétitives",
"covers": "Prospection, facturation, support client."
},
{
"level": "h3",
"heading": "Mieux décider grâce aux données",
"covers": "Analyse de données et intelligence économique."
},
{
"level": "h2",
"heading": "Comment choisir un outil IA ?",
"covers": "Coût, intégration, données, RGPD."
},
{
"level": "h2",
"heading": "Exemples concrets en PME",
"covers": "Cas d'usage chiffrés, avec liens vers les articles du site."
}
],
"faq_candidates": [
"Quel est le meilleur outil IA gratuit pour une PME ?",
"Combien coûte l'intégration de l'IA en entreprise ?",
"L'IA est-elle compatible avec le RGPD ?"
],
"html": "<h1>Outils IA pour entreprise : automatiser, décider, grandir</h1>\n<h2>Quels outils IA pour votre entreprise en 2026 ?</h2>\n <h3>Automatiser les tâches répétitives</h3>\n <h3>Mieux décider grâce aux données</h3>\n<h2>Comment choisir un outil IA ?</h2>\n<h2>Exemples concrets en PME</h2>",
"current": {
"h1": [],
"h2": [],
"h3": [
"8 Prompts ChatGPT pour votre Business Plan",
"Outils pour Manager : Suite Complète d’Outils de Gestion Stratégique Gratuits"
]
},
"analysis_id": "132"
}The headings are illustrative. html and current were computed by the endpoint's own code; current.h3 is shortened (the page has 13).
POST/seo/headingsIllustrative
{
"target_keyword": "outils IA pour entreprise"
}{
"error": {
"code": "invalid_body",
"message": "Send topic (for a new page) or url (to restructure an existing page)."
}
}Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | Neither topic nor url was sent (Send topic (for a new page) or url (to restructure an existing page).). |
| 400invalid_body | A field has the wrong type or is out of bounds (length, range, item count or format); message names it (topic must be at least 2 characters.). |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 422fetch_failed | url was sent, and the page can't be fetched: the domain doesn't resolve, the server doesn't answer within 15 seconds, the host is private, or the page answers with a status of 400 or more. message names the URL and the reason. |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
| 429plan_limit | The account's monthly AI-call allowance can't cover the call this request needs (Monthly AI call allowance reached (300/300 on the free plan). Upgrade at https://autoranko.com/pricing or wait for next month.). It's checked before the body is read. |
| 502upstream_error | The AI request failed (The AI request failed, please retry.) or its result was unusable (The AI returned an incomplete result, please retry.). |
Create a content brief
https://autoranko.com/api/public/v1/seo/content-briefWrites a brief a writer can work from for one keyword, the way the search results see it: the intent that wins, the angle a new page can own, the target length, the questions to answer, the entities to cover, a section structure, internal-link ideas, and a title and meta description.
Describe your business or audience in context to tailor the angle. A field the model leaves out comes back as null, or as an empty list.
Request
application/jsonkeywordstringRequiredThe search query the page will target.- Length
2–150 characters- Example
automatisation des processus métier
contextstringOptionalWho the page is for, in your own words: your business, offer, audience or constraints. It shapes the angle and the internal-link ideas.- Max length
4000 characters- Example
Blog français sur l'IA et la transformation digitale des PME
languagestringOptionalLanguage of the brief. Without it, the AI usually follows the language ofkeyword. Send a language name or code, such asfr,fr-FRorFrench.- Length
2–40 characters- Example
fr
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/content-brief \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"keyword": "automatisation des processus métier",
"context": "Blog français sur l'\''IA et la transformation digitale des PME",
"language": "fr"
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/content-brief", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
keyword: "automatisation des processus métier",
context: "Blog français sur l'IA et la transformation digitale des PME",
language: "fr",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
console.log(`${data.search_intent}, about ${data.target_word_count} words: ${data.angle}`);
for (const q of data.must_answer_questions) console.log("-", q);import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/content-brief",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"keyword": "automatisation des processus métier",
"context": "Blog français sur l'IA et la transformation digitale des PME",
"language": "fr",
},
timeout=130,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
print(f"{data['search_intent']}, about {data['target_word_count']} words: {data['angle']}")
for q in data["must_answer_questions"]:
print("-", q)<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/content-brief');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 130,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'keyword' => 'automatisation des processus métier',
'context' => 'Blog français sur l\'IA et la transformation digitale des PME',
'language' => 'fr',
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
printf("%s, about %d words: %s\n", $data['search_intent'], $data['target_word_count'], $data['angle']);
foreach ($data['must_answer_questions'] as $q) echo "- $q\n";Response
200OKThe brief.
application/jsonkeywordstringThe keyword the brief is for.search_intentstring or nullThe intent the search results reward, ornull.One of
informationalcommercialtransactionalnavigationalintent_notesstring or nullWhat the top results have in common, and what that means for the page.target_word_countinteger or nullRecommended length in words.audiencestring or nullWho the page is for.anglestring or nullThe differentiating take a new page can own.must_answer_questionsarray of stringsQuestions the page must answer (5–8 requested).entities_to_coverarray of stringsTerms and concepts to cover (8–12 requested).suggested_structurearray of objectsSections, in order.suggested_structureitems(2)headingstringSection heading.notesstringWhat the section should do (can be empty).
internal_link_ideasarray of stringsTopics worth linking to or from.title_suggestionstring or nullA title for the page.meta_description_suggestionstring or nullA meta description for the page.success_metricstring or nullWhat ranking well looks like for this query.analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/content-briefIllustrative
{
"keyword": "automatisation des processus métier",
"context": "Blog français sur l'IA et la transformation digitale des PME",
"language": "fr"
}{
"keyword": "automatisation des processus métier",
"search_intent": "informational",
"intent_notes": "Les premiers résultats sont des guides : une définition, des exemples par service, puis des outils. Les pages produit des éditeurs arrivent plus bas.",
"target_word_count": 1800,
"audience": "Dirigeants et responsables des opérations de PME qui veulent réduire les tâches manuelles.",
"angle": "Une méthode en 5 étapes pour choisir les premiers processus à automatiser, avec le gain de temps estimé pour chacun.",
"must_answer_questions": [
"Qu'est-ce que l'automatisation des processus métier ?",
"Quels processus automatiser en premier dans une PME ?",
"Quelle différence entre RPA et automatisation par l'IA ?"
],
"entities_to_cover": [
"RPA",
"workflow",
"BPM",
"ERP",
"intelligence artificielle"
],
"suggested_structure": [
{
"heading": "Définition et enjeux pour une PME",
"notes": "Réponse directe en deux phrases, puis les gains attendus."
},
{
"heading": "Quels processus automatiser en premier ?",
"notes": "Grille de priorisation : volume, répétitivité, risque d'erreur."
}
],
"internal_link_ideas": [
"10 outils IA pour automatiser son business",
"Usage de l'IA en entreprise"
],
"title_suggestion": "Automatisation des processus métier : le guide pour les PME",
"meta_description_suggestion": "Quels processus automatiser en premier, avec quels outils et pour quel gain ? La méthode en 5 étapes pour automatiser les processus métier d'une PME.",
"success_metric": "Top 5 sur la requête et ses variantes (« automatiser les processus », « automatisation BPM ») en 3 à 6 mois.",
"analysis_id": "134"
}The lists are shortened.
POST/seo/content-briefIllustrative
{
"context": "Blog français sur l'IA et la transformation digitale des PME"
}{
"error": {
"code": "invalid_body",
"message": "keyword is required."
}
}Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | keyword is missing or blank (keyword is required.). |
| 400invalid_body | A field has the wrong type or is out of bounds (length, range, item count or format); message names it (context is too long (max 4000 characters).). |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
| 429plan_limit | The account's monthly AI-call allowance can't cover the call this request needs (Monthly AI call allowance reached (300/300 on the free plan). Upgrade at https://autoranko.com/pricing or wait for next month.). It's checked before the body is read. |
| 502upstream_error | The AI request failed (The AI request failed, please retry.) or its result was unusable (The AI returned an incomplete result, please retry.). |
Rewrite copy for SEO
https://autoranko.com/api/public/v1/seo/rewriteRewrites any copy, from a paragraph to a full article, to rank for target_keyword and read better: tighter sentences, concrete claims, natural keyword use and a scannable structure. Facts and HTML tags are kept, and plain text stays plain text. Steer it with instructions.
metrics compares word count and keyword density before and after, measured by Autoranko on the text itself rather than reported by the model. Long inputs, up to 30,000 characters, can take a few minutes.
Request
application/jsoncontentstringRequiredThe copy to rewrite, as plain text or HTML: a paragraph, a landing-page section or a full article.- Length
10–30000 characters- Example
Notre site parle de IA et technologie. Nous avons des articles sur le business et les outils. Lisez nos articles pour en savoir plus sur la transformation digitale.
target_keywordstringOptionalThe search query the copy should rank for. It's also whatmetricscounts.- Max length
120 characters- Example
transformation digitale
instructionsstringOptionalExtra directions, in your own words, such as a length, a tone or a term to avoid.- Max length
2000 characters- Example
Keep it under 60 words.
languagestringOptionalLanguage to write in. Without it, the AI usually keeps the language ofcontent. Send a language name or code, such asfr,fr-FRorFrench.- Length
2–40 characters- Example
fr
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/rewrite \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"content": "Notre site parle de IA et technologie. Nous avons des articles sur le business et les outils. Lisez nos articles pour en savoir plus sur la transformation digitale.",
"target_keyword": "transformation digitale",
"language": "fr"
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/rewrite", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
content: "Notre site parle de IA et technologie. Nous avons des articles sur le business et les outils. Lisez nos articles pour en savoir plus sur la transformation digitale.",
target_keyword: "transformation digitale",
language: "fr",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
const { before, after } = data.metrics;
console.log(`Keyword density: ${before.keyword_density_pct}% -> ${after.keyword_density_pct}%`);
console.log(data.html);import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/rewrite",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"content": "Notre site parle de IA et technologie. Nous avons des articles sur le business et les outils. Lisez nos articles pour en savoir plus sur la transformation digitale.",
"target_keyword": "transformation digitale",
"language": "fr",
},
timeout=310,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
before, after = data["metrics"]["before"], data["metrics"]["after"]
print(f"Keyword density: {before['keyword_density_pct']}% -> {after['keyword_density_pct']}%")
print(data["html"])<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/rewrite');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 310,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'content' => 'Notre site parle de IA et technologie. Nous avons des articles sur le business et les outils. Lisez nos articles pour en savoir plus sur la transformation digitale.',
'target_keyword' => 'transformation digitale',
'language' => 'fr',
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
['before' => $before, 'after' => $after] = $data['metrics'];
printf("Density %s%% -> %s%%\n%s\n", $before['keyword_density_pct'], $after['keyword_density_pct'], $data['html']);Response
200OKThe rewrite, a summary of the changes and before/after metrics.
application/jsonhtmlstringThe rewritten copy, in the same format ascontent: HTML tags are kept, and plain text stays plain text.changes_summaryarray of stringsWhat changed, in 3–6 points.keyword_density_notestring or nullThe model's comment on keyword use, ornull.metricsobjectWord count and keyword density, measured by Autoranko on the text itself (HTML tags ignored).metricskeys(2)beforeobjectcontentas sent.beforekeys(3)TextStatswordsintegerWords in the text, HTML tags ignored.keyword_occurrencesinteger or nullTimestarget_keywordappears as a whole phrase (case and accents ignored), ornullwithout atarget_keyword.keyword_density_pctnumber or nullShare of the words taken by those occurrences, as a percentage with up to 2 decimals, ornullwithout atarget_keyword.
afterobjectThe rewrite.afterkeys(3)TextStatswordsintegerWords in the text, HTML tags ignored.keyword_occurrencesinteger or nullTimestarget_keywordappears as a whole phrase (case and accents ignored), ornullwithout atarget_keyword.keyword_density_pctnumber or nullShare of the words taken by those occurrences, as a percentage with up to 2 decimals, ornullwithout atarget_keyword.
analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/rewriteIllustrative
{
"content": "Notre site parle de IA et technologie. Nous avons des articles sur le business et les outils. Lisez nos articles pour en savoir plus sur la transformation digitale.",
"target_keyword": "transformation digitale",
"language": "fr"
}{
"html": "Réussissez votre transformation digitale grâce à nos articles sur l'IA, la technologie et le business. Comparatifs d'outils, méthodes pas à pas et cas concrets : tout pour passer de l'idée à l'action. Commencez par nos guides sur la transformation digitale.",
"changes_summary": [
"Mot-clé « transformation digitale » placé dès la première phrase.",
"Promesses concrètes : comparatifs d'outils, méthodes pas à pas, cas réels.",
"Appel à l'action plus précis en fin de texte."
],
"keyword_density_note": "2 occurrences sur 39 mots : normal pour un texte aussi court, mais visez 1 à 2 % sur une page complète.",
"metrics": {
"before": {
"words": 28,
"keyword_occurrences": 1,
"keyword_density_pct": 7.14
},
"after": {
"words": 39,
"keyword_occurrences": 2,
"keyword_density_pct": 10.26
}
},
"analysis_id": "136"
}The rewrite is illustrative; metrics was computed by the endpoint's own code.
POST/seo/rewriteIllustrative
{
"content": "Court."
}{
"error": {
"code": "invalid_body",
"message": "content must be at least 10 characters."
}
}Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | content is missing or blank (content is required.). |
| 400invalid_body | A field has the wrong type or is out of bounds (length, range, item count or format); message names it (content is too long (max 30000 characters).). |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
| 429plan_limit | The account's monthly AI-call allowance can't cover the call this request needs (Monthly AI call allowance reached (300/300 on the free plan). Upgrade at https://autoranko.com/pricing or wait for next month.). It's checked before the body is read. |
| 502upstream_error | The AI request failed (The AI request failed, please retry.) or its result was unusable (The AI returned an incomplete result, please retry. or The AI returned an empty rewrite, please retry.). |
Write image alt text
https://autoranko.com/api/public/v1/seo/alt-textsWrites alt text for each image in images. Send each image's file name and the text around it, or its purpose, for the most specific results. Every alt comes with its length, lint warnings and a ready <img> tag; a purely decorative image gets an empty alt.
Add url to give the AI the page as shared context. A URL alone can't reveal each image's file and surroundings, so with only url the endpoint makes no AI call: it returns the page's image counts, the guidelines and a note, and alt_texts is empty.
images is sent, from the account's monthly AI-call allowance (Free 300, Starter 1,500, Pro 6,000 AI calls per calendar month); with url alone it makes none. Allow 120 seconds before your HTTP client times out.Request
application/jsonimagesarrayOptionalThe images to describe: 1–30 objects withcontext(required, up to 1,000 characters: the text around the image, or what it's for) andfilename(optional, up to 300 characters: the file name or URL, which sharpens the alt and gets you a ready<img>tag). Sendingimagesmakes one AI call. Sendimages,urlor both.urlstring (uri)OptionalThe page the images are on, as shared context. Sent alone, it returns the page's image counts and the guidelines, with no AI call. Any publichttporhttpsURL; a bare host such asgladiacteur.comgetshttps://added. At most 3 redirects are followed, and the page must answer within 15 seconds with a status below 400.- Max length
2048 characters- Example
https://gladiacteur.com
target_keywordstringOptionalUsed only where an image genuinely shows it: keyword-stuffed alt text is a spam signal.- Max length
120 characters- Example
tableau de bord IA
languagestringOptionalLanguage of the alt text. Defaults to the page'slangwhenurlis sent. Send a language name or code, such asfr,fr-FRorFrench.- Length
2–40 characters- Example
fr
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/alt-texts \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"images": [
{
"context": "Illustration d'\''un tableau de bord IA analysant des données business",
"filename": "dashboard-ia.png"
}
]
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/alt-texts", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
images: [{
context: "Illustration d'un tableau de bord IA analysant des données business",
filename: "dashboard-ia.png",
}],
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
for (const image of data.alt_texts) {
console.log(image.html);
for (const warning of image.warnings) console.warn(" " + warning);
}import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/alt-texts",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"images": [{
"context": "Illustration d'un tableau de bord IA analysant des données business",
"filename": "dashboard-ia.png",
}],
},
timeout=130,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
for image in data["alt_texts"]:
print(image["html"], *image["warnings"])<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/alt-texts');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 130,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'images' => [[
'context' => 'Illustration d\'un tableau de bord IA analysant des données business',
'filename' => 'dashboard-ia.png',
]],
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
foreach ($data['alt_texts'] as $image) echo $image['html'], ' ', implode(' ', $image['warnings']), "\n";Response
200OKAn alt text per image, or the page's image counts when only url was sent.
application/jsonalt_textsarray of objectsOne entry per item ofimages, in the same order. Empty when onlyurlwas sent.alt_textsitems(8)filenamestring or nullThefilenameyou sent, ornull.contextstringThecontextyou sent.altstringThe alt text, aimed at 125 characters or less. Empty for a decorative image.decorativebooleantruefor a purely decorative image: give italt=""so screen readers skip it.reasonstring or nullWhy this alt text, ornull.lengthintegerCharacters inalt.warningsarray of stringsLint warnings, in English: an empty alt on an image that isn't decorative, over 125 characters, animage of …opening, or a generic or underscored file name.htmlstring or nullA ready<img>tag (srcis thefilename) when a file name was sent, elsenull.
pageobject or nullWithurl: the page's image counts.nullwithouturl.pagekeys(4)urlstring (uri)The page's final URL, after redirects.titlestring or nullThe page title, ornull.images_totalintegerNumber of<img>tags.images_missing_altinteger<img>tags whose alt text is missing or empty.
guidelinesarray of stringsAlt-text best practices, in English: always the same 9 rules.notestring or nullWith onlyurl: the page's image counts and how to get a specific alt for each image.nullwhenimageswas sent.analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/alt-textsIllustrative
{
"images": [
{
"context": "Illustration d'un tableau de bord IA analysant des données business",
"filename": "dashboard-ia.png"
},
{
"context": "Photo de l'équipe lors d'un atelier sur l'IA générative",
"filename": "IMG_0042.jpg"
}
]
}{
"alt_texts": [
{
"filename": "dashboard-ia.png",
"context": "Illustration d'un tableau de bord IA analysant des données business",
"alt": "Tableau de bord d'IA analysant des données business sous forme de graphiques",
"decorative": false,
"reason": "Décrit ce que montre l'illustration, dans le contexte business de la page.",
"length": 76,
"warnings": [],
"html": "<img src=\"dashboard-ia.png\" alt=\"Tableau de bord d'IA analysant des données business sous forme de graphiques\">"
},
{
"filename": "IMG_0042.jpg",
"context": "Photo de l'équipe lors d'un atelier sur l'IA générative",
"alt": "Équipe réunie autour d'un écran pendant un atelier sur l'IA générative",
"decorative": false,
"reason": "Précise la scène et le sujet de l'atelier, sans bourrage de mots-clés.",
"length": 70,
"warnings": [
"The filename is generic. Rename it descriptively with hyphens before uploading."
],
"html": "<img src=\"IMG_0042.jpg\" alt=\"Équipe réunie autour d'un écran pendant un atelier sur l'IA générative\">"
}
],
"page": null,
"guidelines": [
"Describe what the image shows, specifically: the subject, the action and the detail that matters on this page. Keep it under ~125 characters.",
"Skip \"image of\" and \"photo of\": screen readers already announce that it is an image."
],
"note": null,
"analysis_id": "137"
}The alt texts are illustrative; length, warnings and html were computed by the endpoint's own code. guidelines is shortened: it always lists the same 9 rules.
POST/seo/alt-textsIllustrative
{
"url": "https://gladiacteur.com"
}{
"alt_texts": [],
"page": {
"url": "https://gladiacteur.com/",
"title": "Gladiacteur - IA, Technologie et Business : Outils, Tendances & Transformation Digitale",
"images_total": 28,
"images_missing_alt": 6
},
"guidelines": [
"Describe what the image shows, specifically: the subject, the action and the detail that matters on this page. Keep it under ~125 characters.",
"Skip \"image of\" and \"photo of\": screen readers already announce that it is an image."
],
"note": "https://gladiacteur.com/ has 28 images, 6 without alt text. A URL alone doesn't expose each image's file and surrounding text, so send images (filename + surrounding text for each) to get a specific alt for every image.",
"analysis_id": "138"
}Computed by the endpoint's own code from the live gladiacteur.com homepage. guidelines is shortened.
POST/seo/alt-textsIllustrative
{
"images": [
{
"alt": "Logo Gladiacteur",
"filename": "logo.svg"
}
]
}{
"error": {
"code": "invalid_body",
"message": "Unknown field \"images[0].alt\". Allowed fields: context, filename."
}
}Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | Neither images nor url was sent (Send images (a list of {context, filename?}; best results) or url (page-level audit and guidelines).). |
| 400invalid_body | A field has the wrong type or is out of bounds (length, range, item count or format); message names it (images[0].context is required.). |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 422fetch_failed | url was sent, and the page can't be fetched: the domain doesn't resolve, the server doesn't answer within 15 seconds, the host is private, or the page answers with a status of 400 or more. message names the URL and the reason. |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
| 429plan_limit | images was sent and the account's monthly AI-call allowance can't cover the call (Monthly AI call allowance reached (300/300 on the free plan). Upgrade at https://autoranko.com/pricing or wait for next month.). With url alone, no allowance is needed. |
| 502upstream_error | The AI request failed (The AI request failed, please retry.) or its result was unusable (The AI returned an incomplete result, please retry. or The AI returned no alt texts, please retry.). |
Generate robots.txt and a sitemap
https://autoranko.com/api/public/v1/seo/robots-sitemapBuilds a robots.txt and an XML sitemap for a site from the pages you list: exact and correctly escaped for 1 URL or 500, with duplicates removed. Pages without priority or changefreq get defaults from their path.
checks reviews the result for crawl problems: sitemap URLs blocked by your own Disallow rules, blocked CSS or JavaScript, utility pages (login, cart, search), query strings, inconsistent trailing slashes and missing lastmod dates. instructions says where to upload each file and how to submit the sitemap.
Request
application/jsonsite_urlstring (uri)RequiredThe site's home URL. Only its origin is used: every URL in the sitemap is on this host and uses its scheme. It isn't fetched.- Max length
2048 characters- Example
https://gladiacteur.com
pagesarrayRequiredThe pages to list: 1–500 objects withpath(required: a path such as/contact/, or an absolute URL on the same host), and optionallypriority(a number from 0 to 1),changefreq(one ofalways,hourly,daily,weekly,monthly,yearly,never) andlastmod(the date the page last changed meaningfully,YYYY-MM-DDor an ISO 8601 date-time, not in the future). Without them,priorityis1.0for the homepage,0.8,0.6or0.5by depth and0.3for legal pages;changefreqisweeklyfor the homepage and blog index,yearlyfor legal pages andmonthlyotherwise.disallow_pathsarray of stringsOptionalPaths crawlers should skip, oneDisallowrule each: up to 100, each starting with/or*and up to 500 characters. The wildcards*and$work as in Google's robots.txt. Without any, robots.txt allows everything.- Max items
100- Example
["/wp-admin/"]
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/robots-sitemap \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"site_url": "https://gladiacteur.com",
"pages": [
{
"path": "/"
}
]
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/robots-sitemap", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
site_url: "https://gladiacteur.com",
pages: [{
path: "/",
}],
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
const { writeFileSync } = await import("node:fs");
writeFileSync("robots.txt", data.robots_txt);
writeFileSync("sitemap.xml", data.sitemap_xml);import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/robots-sitemap",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"site_url": "https://gladiacteur.com",
"pages": [{
"path": "/",
}],
},
timeout=30,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
open("robots.txt", "w").write(data["robots_txt"])
open("sitemap.xml", "w").write(data["sitemap_xml"])<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/robots-sitemap');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'site_url' => 'https://gladiacteur.com',
'pages' => [[
'path' => '/',
]],
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
file_put_contents('robots.txt', $data['robots_txt']);
file_put_contents('sitemap.xml', $data['sitemap_xml']);Response
200OKBoth files, where to serve them, and the crawl checks.
application/jsonrobots_txtstringThe complete robots.txt:User-agent: *, oneDisallowline perdisallow_pathsentry (orAllow: /without any), and the sitemap URL.sitemap_xmlstringThe complete XML sitemap (sitemaps.org 0.9): one<url>per unique page with<loc>,<lastmod>when sent,<changefreq>and<priority>.robots_urlstring (uri)Where robots.txt must be served: the site's origin plus/robots.txt.sitemap_urlstring (uri)Where to serve the sitemap, as robots.txt references it: the origin plus/sitemap.xml.url_countintegerURLs in the sitemap, after removing duplicates.checksarray of objectsCrawl checks, in this order:crawlable_site,sitemap_vs_robots,render_resources,canonical_urls_only,indexable_pages_only,trailing_slash_consistency,url_hygiene,https,homepage_listed,duplicates,lastmodandpriority_changefreq(informational: Google ignores both tags).checksitems(3)SeoCheckcheckstringMachine-readable name of the check, such astitle_widthorsitemap_vs_robots.passbooleantruewhen the check passes.notestringWhat was measured or found and, on a failure, what to do about it. Always in English.
instructionsarray of stringsThree steps: where to upload each file, and how to submit the sitemap to Google Search Console.analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/robots-sitemapIllustrative
{
"site_url": "https://gladiacteur.com",
"pages": [
{
"path": "/",
"changefreq": "daily"
},
{
"path": "/ia-en-entreprise/",
"lastmod": "2026-10-20"
},
{
"path": "/10-outils-ia-pour-automatiser-son-business/",
"lastmod": "2026-09-14"
},
{
"path": "/contact/"
}
],
"disallow_paths": [
"/wp-admin/"
]
}{
"robots_txt": "# robots.txt for https://gladiacteur.com - generated by Autoranko\nUser-agent: *\nDisallow: /wp-admin/\n\nSitemap: https://gladiacteur.com/sitemap.xml\n",
"sitemap_xml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n <url>\n <loc>https://gladiacteur.com/</loc>\n <changefreq>daily</changefreq>\n <priority>1.0</priority>\n </url>\n <url>\n <loc>https://gladiacteur.com/ia-en-entreprise/</loc>\n <lastmod>2026-10-20</lastmod>\n <changefreq>monthly</changefreq>\n <priority>0.8</priority>\n </url>\n <url>\n <loc>https://gladiacteur.com/10-outils-ia-pour-automatiser-son-business/</loc>\n <lastmod>2026-09-14</lastmod>\n <changefreq>monthly</changefreq>\n <priority>0.8</priority>\n </url>\n <url>\n <loc>https://gladiacteur.com/contact/</loc>\n <changefreq>monthly</changefreq>\n <priority>0.8</priority>\n </url>\n</urlset>\n",
"robots_url": "https://gladiacteur.com/robots.txt",
"sitemap_url": "https://gladiacteur.com/sitemap.xml",
"url_count": 4,
"checks": [
{
"check": "sitemap_vs_robots",
"pass": true,
"note": "No sitemap URL is blocked by robots.txt."
},
{
"check": "indexable_pages_only",
"pass": true,
"note": "No utility pages (login, cart, search, thank-you) are listed."
},
{
"check": "lastmod",
"pass": false,
"note": "2 URL(s) have no lastmod. Send the date each page last changed meaningfully. Google trusts lastmod only when it's consistently accurate, so never stamp every page with today's date."
},
{
"check": "priority_changefreq",
"pass": true,
"note": "Google ignores <priority> and <changefreq>. They are filled in (defaults from page depth) for other crawlers; an accurate URL list and lastmod are what count."
}
],
"instructions": [
"Upload robots.txt to the web root so it is served at https://gladiacteur.com/robots.txt. It only works at the root of the host.",
"Upload sitemap.xml to the web root so it is served at https://gladiacteur.com/sitemap.xml with an XML content type.",
"In Google Search Console (and Bing Webmaster Tools), open Sitemaps and submit sitemap.xml. Regenerate it whenever you add, remove or redirect pages."
],
"analysis_id": "139"
}Computed by the endpoint's own code; only analysis_id is illustrative. checks is shortened to 4 of 12.
POST/seo/robots-sitemapIllustrative
{
"site_url": "https://gladiacteur.com",
"pages": [
{
"path": "/"
},
{
"path": "https://example.com/a-propos/"
}
]
}{
"error": {
"code": "invalid_body",
"message": "pages[1].path must be a path such as \"/about\", or a URL on gladiacteur.com: a sitemap can only list its own host's URLs."
}
}Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | site_url or pages is missing (site_url is required. or pages is required: a list of {path, priority?, changefreq?, lastmod?} (1-500 items).). |
| 400invalid_body | A path in pages is on another host (pages[1].path must be a path such as "/about", or a URL on gladiacteur.com: a sitemap can only list its own host's URLs.). |
| 400invalid_body | A field has the wrong type or is out of bounds (length, range, item count or format); message names it (pages[0].lastmod must be a date (YYYY-MM-DD) or an ISO 8601 datetime.). |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
Preview a Google result
https://autoranko.com/api/public/v1/seo/serp-previewShows how a title, meta description and URL render on Google's results page. Widths are measured in pixels with Arial's metrics, the way Google truncates: about 580px for a desktop title, 920px for a description (two lines) and 680px for a description on mobile. preview holds the text exactly as searchers would see it, cut where Google would cut it, and the breadcrumb URL line.
checks passes or fails ten rules: lengths and widths, keyword placement (exact when you send keyword), a readable HTTPS URL, casing, keyword stuffing, and whether the description adds to the title. Nothing is fetched: it works on drafts too.
Request
application/jsontitlestringRequiredThe title tag to preview.- Max length
300 characters- Example
Gladiacteur - IA, Technologie et Business : Outils & Tendances
descriptionstringRequiredThe meta description to preview.- Max length
1000 characters- Example
Découvrez comment l'IA et l'automatisation transforment les entreprises: outils, tendances et stratégies concrètes.
urlstring (uri)RequiredThe page's URL, for the breadcrumb line and the URL checks: a publichttporhttpsURL (a bare host getshttps://). It isn't fetched.- Max length
2048 characters- Example
https://gladiacteur.com/
keywordstringOptionalThe query the page targets. With it,keyword_placementchecks that it's early in the title and in the description's first 120 characters; without it, the check only compares the title's lead words with the description.- Max length
120 characters- Example
IA business
savebooleanOptionalSave the result to the account's SEO Lab history, shown in Dashboard → SEO Lab and listed by GET /seo/analyses. Sendfalseto keep nothing;analysis_idis thennull. Must be a JSON boolean.- Default
true- Example
true
curl -X POST https://autoranko.com/api/public/v1/seo/serp-preview \
-H "Authorization: Bearer $AUTORANKO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Gladiacteur - IA, Technologie et Business : Outils & Tendances",
"description": "Découvrez comment l'\''IA et l'\''automatisation transforment les entreprises: outils, tendances et stratégies concrètes.",
"url": "https://gladiacteur.com/",
"keyword": "IA business"
}'const res = await fetch("https://autoranko.com/api/public/v1/seo/serp-preview", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Gladiacteur - IA, Technologie et Business : Outils & Tendances",
description: "Découvrez comment l'IA et l'automatisation transforment les entreprises: outils, tendances et stratégies concrètes.",
url: "https://gladiacteur.com/",
keyword: "IA business",
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
console.log(data.preview.title_shown);
for (const c of data.checks) if (!c.pass) console.log(`${c.check}: ${c.note}`);import os
import requests
res = requests.post(
"https://autoranko.com/api/public/v1/seo/serp-preview",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
json={
"title": "Gladiacteur - IA, Technologie et Business : Outils & Tendances",
"description": "Découvrez comment l'IA et l'automatisation transforment les entreprises: outils, tendances et stratégies concrètes.",
"url": "https://gladiacteur.com/",
"keyword": "IA business",
},
timeout=30,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
print(data["preview"]["title_shown"])
print("Failed:", [c["check"] for c in data["checks"] if not c["pass"]])<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/serp-preview');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AUTORANKO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'title' => 'Gladiacteur - IA, Technologie et Business : Outils & Tendances',
'description' => 'Découvrez comment l\'IA et l\'automatisation transforment les entreprises: outils, tendances et stratégies concrètes.',
'url' => 'https://gladiacteur.com/',
'keyword' => 'IA business',
]),
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
echo $data['preview']['title_shown'], "\n";
foreach ($data['checks'] as $c) if (!$c['pass']) echo "{$c['check']}: {$c['note']}\n";Response
200OKThe rendered preview, the measurements and the checks.
application/jsonpreviewobjectThe result as searchers would see it on desktop.previewkeys(3)title_shownstringThe title as displayed: cut at a word boundary, with...added, when it's wider than about 580px.description_shownstringThe description as displayed, cut the same way after about 920px (two lines).breadcrumbstringThe URL line under the site name: the host, then up to 3 path segments, separated by›.
measurementsobjectLengths and rendered widths. Widths are approximate pixels, computed from Arial's font metrics.measurementskeys(3)titleobjectThe title, at the size of a desktop result title.titlekeys(5)charsintegerLength in characters.pixelsintegerRendered width in pixels.limit_pixelsintegerGoogle's desktop limit for titles: 580.truncatedbooleantruewhen Google would cut it.fontstringThe font the widths assume:20px Arial (approx.).
descriptionobjectThe meta description, at the size of a result snippet.descriptionkeys(7)charsintegerLength in characters.pixelsintegerRendered width in pixels, on one line.limit_pixelsintegerGoogle's desktop limit, two lines: 920.mobile_limit_pixelsintegerGoogle's mobile limit: 680.truncatedbooleantruewhen Google would cut it on desktop.fits_mobilebooleantruewhen it fits on mobile too.fontstringThe font the widths assume:14px Arial (approx.).
urlobjectThe URL.urlkeys(3)charsintegerLength in characters.path_depthinteger or nullNumber of path segments (/blog/post/is 2), ornullif the URL can't be parsed.httpsboolean or nulltruefor an HTTPS URL, ornullif the URL can't be parsed.
checksarray of objectsTen pass/fail checks, in this order:title_length,title_width,description_length,description_width,keyword_placement,url_readable,https,title_case(not mostly uppercase),title_repetition(no keyword stuffing) andtitle_vs_description(the description adds to the title).keyword_placementis exact when a keyword is given; otherwise it's informational, comparing the title's lead words with the description.checksitems(3)SeoCheckcheckstringMachine-readable name of the check, such astitle_widthorsitemap_vs_robots.passbooleantruewhen the check passes.notestringWhat was measured or found and, on a failure, what to do about it. Always in English.
analysis_idstring or nullID of the result saved to the account's SEO Lab history (a 64-bit integer serialized as a string); fetch it again with GET /seo/analyses/{id}.nullwhensavewasfalse, or in the rare case the save failed: the result is returned either way.
Examples
POST/seo/serp-previewIllustrative
{
"title": "Gladiacteur - IA, Technologie et Business : Outils & Tendances",
"description": "Découvrez comment l'IA et l'automatisation transforment les entreprises: outils, tendances et stratégies concrètes.",
"url": "https://gladiacteur.com/",
"keyword": "IA business"
}{
"preview": {
"title_shown": "Gladiacteur - IA, Technologie et Business : Outils & Tendances",
"description_shown": "Découvrez comment l'IA et l'automatisation transforment les entreprises: outils, tendances et stratégies concrètes.",
"breadcrumb": "gladiacteur.com"
},
"measurements": {
"title": {
"chars": 62,
"pixels": 559,
"limit_pixels": 580,
"truncated": false,
"font": "20px Arial (approx.)"
},
"description": {
"chars": 115,
"pixels": 706,
"limit_pixels": 920,
"mobile_limit_pixels": 680,
"truncated": false,
"fits_mobile": false,
"font": "14px Arial (approx.)"
},
"url": {
"chars": 24,
"path_depth": 0,
"https": true
}
},
"checks": [
{
"check": "title_length",
"pass": true,
"note": "62 characters, over the usual 60, but narrow enough to fit (559px). Google cuts by pixel width, not characters."
},
{
"check": "title_width",
"pass": true,
"note": "About 559px of ~580px, so it shows in full on desktop."
},
{
"check": "description_width",
"pass": true,
"note": "About 706px: fits two desktop lines (~920px). On mobile (~680px) it will be cut, so put the key promise first."
},
{
"check": "keyword_placement",
"pass": false,
"note": "\"IA business\" is front-loaded in the title (with all its terms). Add it to the first 120 characters of the description: Google bolds matching query words, and mobile cuts the rest."
},
{
"check": "title_vs_description",
"pass": true,
"note": "The description adds information beyond the title."
}
],
"analysis_id": "140"
}Computed by the endpoint's own code; only analysis_id is illustrative. checks is shortened to 5 of 10.
POST/seo/serp-previewIllustrative
{
"description": "Découvrez comment l'IA et l'automatisation transforment les entreprises: outils, tendances et stratégies concrètes.",
"url": "https://gladiacteur.com/"
}{
"error": {
"code": "invalid_body",
"message": "title is required."
}
}Errors
| Error | When |
|---|---|
| 400invalid_body | The body isn't a JSON object (Invalid JSON body. or The JSON body must be an object.). |
| 400invalid_body | The body has a field the endpoint doesn't accept (Unknown field "…"). Names are exact, and a near miss such as targetKeyword gets a hint to the right one. |
| 400invalid_body | title, description or url is missing (title is required.). |
| 400invalid_body | A field has the wrong type or is out of bounds (length, range, item count or format); message names it (description is too long (max 1000 characters).). |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 413invalid_body | The body is larger than 2 MB (Request body too large (max 2 MB).). |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
List saved analyses
https://autoranko.com/api/public/v1/seo/analysesLists the account's saved toolkit results, its SEO Lab history, newest first. Each entry is a summary without the request or the result: fetch one with GET /seo/analyses/{id}. Dashboard → SEO Lab shows the same history.
Filter by endpoint with kind. Page through the list with limit and offset until a page returns fewer than limit items; there's no total count.
save: false leaves nothing here.Request
kindstringOptionalOnly return results from this endpoint. An unknown value is rejected with 400 invalid_body.One of
analyzekeywordsarticlearticle_shortmeta_tagsopen_graphschemaheadingscontent_briefrewritealt_textsrobots_sitemapserp_preview- Example
analyze
limitintegerOptionalPage size. Values outside 1–100 are clamped to that range, not rejected.- Default
50- Range
1–100- Example
20
offsetintegerOptionalHow many results to skip, for pagination. Out-of-range values are clamped.- Default
0- Range
0–1000000- Example
0
curl "https://autoranko.com/api/public/v1/seo/analyses?kind=analyze&limit=20" \
-H "Authorization: Bearer $AUTORANKO_TOKEN"const res = await fetch("https://autoranko.com/api/public/v1/seo/analyses?kind=analyze&limit=20", {
headers: { Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}` },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
for (const a of data.analyses) console.log(a.id, a.kind, a.subject, a.created_at);import os
import requests
res = requests.get(
"https://autoranko.com/api/public/v1/seo/analyses",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
params={"kind": "analyze", "limit": 20},
timeout=30,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
for a in data["analyses"]:
print(a["id"], a["kind"], a["subject"], a["created_at"])<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/analyses?kind=analyze&limit=20');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AUTORANKO_TOKEN')],
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
foreach ($data['analyses'] as $a) {
echo "{$a['id']} {$a['kind']} {$a['subject']} {$a['created_at']}\n";
}Response
200OKOne page of saved results, newest first.
application/jsonanalysesarray of objectsSaved results, newest first.analysesitems(4)SeoAnalysisSummaryidstringAnalysis ID: a 64-bit integer serialized as a string. It's theanalysis_idthe endpoint returned.kindstringThe endpoint that produced the result: its last path segment with_for-, such asarticle_shortfor POST /seo/article-short.One of
analyzekeywordsarticlearticle_shortmeta_tagsopen_graphschemaheadingscontent_briefrewritealt_textsrobots_sitemapserp_previewsubjectstringWhat the request was about: the page URL, topic, keyword or site, depending on the endpoint (at most 500 characters).created_atstring (date-time)When the result was saved.
limitintegerThe page size that was applied (after clamping).offsetintegerThe offset that was applied (after clamping).
Examples
GET/seo/analyses?limit=3Illustrative
{
"analyses": [
{
"id": "141",
"kind": "article",
"subject": "Comment automatiser sa prospection B2B avec l'IA en 2026",
"created_at": "2026-10-26T09:52:37.904Z"
},
{
"id": "140",
"kind": "serp_preview",
"subject": "https://gladiacteur.com/",
"created_at": "2026-10-26T09:49:12.118Z"
},
{
"id": "139",
"kind": "robots_sitemap",
"subject": "https://gladiacteur.com",
"created_at": "2026-10-26T09:49:10.551Z"
}
],
"limit": 3,
"offset": 0
}GET/seo/analyses?kind=auditIllustrative
{
"error": {
"code": "invalid_body",
"message": "kind must be one of: analyze, keywords, article, article_short, meta_tags, open_graph, schema, headings, content_brief, rewrite, alt_texts, robots_sitemap, serp_preview."
}
}Errors
| Error | When |
|---|---|
| 400invalid_body | kind isn't one of the analysis kinds (kind must be one of: …). The code is invalid_body even though kind is a query parameter. |
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
Get a saved analysis
https://autoranko.com/api/public/v1/seo/analyses/{id}Returns one saved toolkit result: the validated request that produced it and the full result, as the endpoint returned it (without analysis_id). id is the analysis_id from the toolkit response, or an id from GET /seo/analyses.
Requests and results are stored as JSON documents, so their keys can come back in a different order than in the original response.
Request
idintegerRequired
curl https://autoranko.com/api/public/v1/seo/analyses/129 \
-H "Authorization: Bearer $AUTORANKO_TOKEN"const res = await fetch("https://autoranko.com/api/public/v1/seo/analyses/129", {
headers: { Authorization: `Bearer ${process.env.AUTORANKO_TOKEN}` },
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
const { analysis } = data;
console.log(analysis.kind, analysis.subject, analysis.created_at);
console.log(JSON.stringify(analysis.result, null, 2));import os
import requests
res = requests.get(
"https://autoranko.com/api/public/v1/seo/analyses/129",
headers={"Authorization": f"Bearer {os.environ['AUTORANKO_TOKEN']}"},
timeout=30,
)
data = res.json()
if not res.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
analysis = data["analysis"]
print(analysis["kind"], analysis["subject"], analysis["created_at"])
print(analysis["result"])<?php
$ch = curl_init('https://autoranko.com/api/public/v1/seo/analyses/129');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AUTORANKO_TOKEN')],
]);
$data = json_decode(curl_exec($ch), true);
if (isset($data['error'])) throw new RuntimeException($data['error']['message']);
$analysis = $data['analysis'];
echo $analysis['kind'], ' ', $analysis['subject'], ' ', $analysis['created_at'], "\n";
print_r($analysis['result']);Response
200OKThe saved result, with its request.
application/jsonanalysisobjectThe saved result.analysiskeys(6)SeoAnalysisidstringAnalysis ID: a 64-bit integer serialized as a string. It's theanalysis_idthe endpoint returned.kindstringThe endpoint that produced the result: its last path segment with_for-, such asarticle_shortfor POST /seo/article-short.One of
analyzekeywordsarticlearticle_shortmeta_tagsopen_graphschemaheadingscontent_briefrewritealt_textsrobots_sitemapserp_previewsubjectstringWhat the request was about: the page URL, topic, keyword or site, depending on the endpoint (at most 500 characters).requestobjectThe request as validated, withoutsave: values normalized (https://added to a bare host, for example) and defaults filled in (mode,word_count,tone, …).resultobjectThe response body the endpoint returned, withoutanalysis_id.created_atstring (date-time)When the result was saved.
Examples
GET/seo/analyses/129Illustrative
{
"analysis": {
"id": "129",
"kind": "keywords",
"subject": "outils IA pour PME",
"request": {
"mode": "ideas",
"topic": "outils IA pour PME",
"country": "FR",
"language": "fr"
},
"result": {
"mode": "ideas",
"keywords": [
{
"cpc": 2.4,
"volume": 880,
"keyword": "outils ia pour pme",
"difficulty": 38,
"competition": "MEDIUM",
"competition_index": 54
},
{
"cpc": 1.85,
"volume": 590,
"keyword": "meilleur outil ia gratuit entreprise",
"difficulty": 35,
"competition": "MEDIUM",
"competition_index": 47
}
],
"estimated": true,
"seeds_used": [
"outils IA pour PME"
]
},
"created_at": "2026-10-26T09:41:58.372Z"
}
}The keywords example above as stored: keys inside request and result come back shortest first, and keywords is shortened.
GET/seo/analyses/9999Illustrative
{
"error": {
"code": "not_found",
"message": "Analysis not found."
}
}Errors
| Error | When |
|---|---|
| 401missing_token | The Authorization: Bearer … header is missing. |
| 401invalid_token | The token is malformed, unknown or revoked. |
| 404not_found | No saved analysis with this id belongs to your account (Analysis not found.). |
| 429rate_limited | The token made more than 120 requests in the last 60 seconds. |
API version v1. Every path on this page is relative to https://autoranko.com/api/public/v1.