Capture & export

Figer une sélection pays × indicateurs et ses valeurs réelles sous un identifiant immuable, la partager (oEmbed, page HTML canonique), l'exporter en JSON/CSV/SVG et autres formats, ou obtenir un graphique SVG autonome sans passer par une capture.

POST/api/capture

Fige une sélection pays × indicateurs et ses valeurs réelles sous un identifiant immuable. Requiert une session (cookie) ou une clé API — la création n'est pas anonyme.

Paramètre
Type
Requis
Défaut
Description
countries
list[str]
oui
Codes pays de la sélection (jusqu'à 20).
indicators
list[str]
oui
Codes d'indicateurs de la sélection (jusqu'à 20).
start
int | null
non
null
Année de début de la fenêtre figée.
end
int | null
non
null
Année de fin (au-delà de 50 années entre start/end : erreur).
render
dict | null
non
null
Options de rendu (palette, grille, type de graphe, dimensions, fond, légende/valeurs/dernier point, per_capita). Validé par normalisation : un champ non reconnu ou hors bornes retombe silencieusement sur le défaut, ne fait jamais échouer la création.
Code
Erreur
Cas
401
capture_requires_account
Ni session ni clé API fournie (une clé invalide est rejetée en amont avec invalid_api_key).
400
capture_too_large
Aucun pays, aucun indicateur, plus de 20 pays, plus de 20 indicateurs, période inversée (start > end), ou plus de 50 années demandées.
400
unknown_indicator
Un code d'indicateur n'existe pas dans le catalogue.
404
unknown_countries
Un ou plusieurs codes pays sont inconnus.
429
too_many_requests_minute
Plus de 10 créations par minute, comptées par clé API si présente, sinon par IP.
CURL
curl -X POST -H "X-API-Key: $ATLAS_KEY" -H "Content-Type: application/json" \
  -d '{"countries":["FRA","DEU"],"indicators":["NY.GDP.MKTP.CD"],"start":2018,"end":2022}' \
  "https://atlasfeed.fr/api/capture"
PYTHON
import requests

r = requests.post(
    "https://atlasfeed.fr/api/capture",
    headers={"X-API-Key": ATLAS_KEY},
    json={
        "countries": ["FRA", "DEU"],
        "indicators": ["NY.GDP.MKTP.CD"],
        "start": 2018,
        "end": 2022,
    },
)
print(r.json())
JAVASCRIPT
fetch("https://atlasfeed.fr/api/capture", {
  method: "POST",
  headers: { "X-API-Key": ATLAS_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    countries: ["FRA", "DEU"],
    indicators: ["NY.GDP.MKTP.CD"],
    start: 2018,
    end: 2022,
  }),
}).then(r => r.json()).then(console.log);
RÉPONSE
{"id": "4761xbw1lGI", "url": "/c/4761xbw1lGI"}
GET/api/capture/{capture_id}

Projection d'une capture figée. format=json est la projection native ; 11 autres formats la mettent en forme (html/pdf redirigent vers /c/{id}, csv/markdown/bibtex/python/r en texte, svg/png en image, xlsx/pptx en Office). Un format connu mais non implémenté par ce déploiement renvoie 501, pas 404 (la capture existe, c'est la projection qui manque — cas de png sans l'extra png installé).

Paramètre
Type
Requis
Défaut
Description
capture_id
str (path)
oui
Identifiant renvoyé par POST /api/capture.
format
str
non
json
json, csv, markdown, bibtex, python, r, svg, png, xlsx, pptx, html, pdf.
indicator
str
non
null
Restreint la projection graphique à un seul indicateur — une capture peut porter jusqu'à 20 indicateurs d'unités différentes, superposables sur un axe unique donnerait une image fausse.
Code
Erreur
Cas
400
capture_unknown_format
format ne fait partie d'aucune des 12 valeurs reconnues (ex. ?format=bidon).
404
capture_not_found
capture_id inexistant.
501
capture_format_not_implemented
Format reconnu mais pas servi par ce déploiement (ex. png sans l'extra png).
CURL
curl "https://atlasfeed.fr/api/capture/4761xbw1lGI?format=json"
PYTHON
import requests

r = requests.get("https://atlasfeed.fr/api/capture/4761xbw1lGI", params={"format": "json"})
print(r.json())
JAVASCRIPT
fetch("https://atlasfeed.fr/api/capture/4761xbw1lGI?format=json")
  .then(r => r.json())
  .then(console.log);
RÉPONSE
{
  "id": "4761xbw1lGI",
  "createdAt": "2026-09-09T11:59:35.011662+00:00",
  "lastViewedAt": null,
  "countries": [
    {"code": "FRA", "name": "France", "flagEmoji": "🇫🇷"},
    {"code": "DEU", "name": "Allemagne", "flagEmoji": "🇩🇪"}
  ],
  "indicators": [
    {
      "code": "NY.GDP.MKTP.CD", "label": "PIB", "theme": "Économie", "unit": "US$ courants",
      "fmt": "currency", "headline": true,
      "attribution": {"source": "worldbank", "organization": "World Bank", "url": "https://data.worldbank.org", "retrievedOn": "2026-09-09", "citation": "World Bank, consulté via Atlas le 2026-09-09."}
    }
  ],
  "series": [
    {"country": "FRA", "indicator": "NY.GDP.MKTP.CD", "points": [{"year": 2018, "value": 2781576320884.39}], "unavailable": false}
  ]
}
?format=csv renvoie du texte (text/csv; charset=utf-8). ?format=html ou ?format=pdf renvoient une redirection 302 vers /c/{id} (le PDF s'obtient en imprimant cette page, pas une projection séparée). ?format=svg renvoie du SVG (image/svg+xml, Content-Disposition: inline).
DELETE/api/capture/{capture_id}

Supprime une capture et son lien d'appartenance — uniquement pour son propriétaire.

Route authentifiée par cookie de session (require_session + require_csrf), pas par X-API-Key — elle sert l'interface /compte/ du site Atlas, pas une intégration API externe. Incluse ici à titre de référence.
Paramètre
Type
Requis
Défaut
Description
capture_id
str (path)
oui
Identifiant de la capture à supprimer.
Code
Erreur
Cas
404
capture_not_found
capture_id inexistant, ou n'appartenant pas au compte connecté — les deux cas sont indistingables par design, pour ne jamais faire de cette route un oracle de propriété.
CURL
curl -X DELETE "https://atlasfeed.fr/api/capture/4761xbw1lGI" \
  -H "Cookie: atlas_session=..." \
  -H "X-Atlas-CSRF: 1"
PYTHON
import requests

r = requests.delete(
    "https://atlasfeed.fr/api/capture/4761xbw1lGI",
    cookies={"atlas_session": "..."},
    headers={"X-Atlas-CSRF": "1"},
)
print(r.json())
JAVASCRIPT
fetch("https://atlasfeed.fr/api/capture/4761xbw1lGI", {
  method: "DELETE",
  credentials: "include",
  headers: { "X-Atlas-CSRF": "1" }
}).then(r => r.json()).then(console.log);
RÉPONSE
{"ok": true}
GET/api/oembed

Point d'entrée oEmbed pour les captures, découvert via la balise <link rel="alternate" type="application/json+oembed"> de /c/{id}. N'accepte que ses propres URL de capture. Ne déclenche jamais de comptage de consultation (un aperçu robot de réseau social n'est pas une consultation humaine).

Paramètre
Type
Requis
Défaut
Description
url
str
oui
URL absolue ou chemin relatif /c/{id}.
format
str
non
json
Seul "json" est servi (XML autorisé par la spec oEmbed, jamais implémenté ici).
maxwidth
int
non
Borné entre 16 et 4000.
maxheight
int
non
Borné entre 16 et 4000.
Code
Erreur
Cas
501
oembed_format_unsupported
format ≠ "json".
404
oembed_url_unsupported
url ne pointe pas vers une capture (/c/{id}).
404
capture_not_found
L'id extrait de l'URL n'existe pas.
CURL
curl "https://atlasfeed.fr/api/oembed?url=https://atlasfeed.fr/c/4761xbw1lGI"
PYTHON
import requests

r = requests.get(
    "https://atlasfeed.fr/api/oembed",
    params={"url": "https://atlasfeed.fr/c/4761xbw1lGI"},
)
print(r.json())
JAVASCRIPT
fetch("https://atlasfeed.fr/api/oembed?url=https://atlasfeed.fr/c/4761xbw1lGI")
  .then(r => r.json())
  .then(console.log);
RÉPONSE
{
  "version": "1.0", "type": "rich", "provider_name": "Atlas", "provider_url": "https://atlasfeed.fr",
  "title": "Capture Atlas 4761xbw1lGI", "width": 720, "height": 446,
  "html": "\"Capture"
}
GET/c/{capture_id}

Page HTML canonique d'une capture — tableau des valeurs figées et attribution, faite pour être citée ou imprimée sans dépendance JS.

Paramètre
Type
Requis
Défaut
Description
capture_id
str (path)
oui
Identifiant de la capture.
Code
Erreur
Cas
404
capture_not_found
Réponse JSON, même si la route sert normalement du HTML.
CURL
curl "https://atlasfeed.fr/c/4761xbw1lGI"
PYTHON
import requests

r = requests.get("https://atlasfeed.fr/c/4761xbw1lGI")
print(r.text[:200])
JAVASCRIPT
fetch("https://atlasfeed.fr/c/4761xbw1lGI")
  .then(r => r.text())
  .then(html => console.log(html.slice(0, 200)));
RÉPONSE
Contenu : text/html. Page HTML complète (tableau des valeurs, attribution des sources, balise
oEmbed de découverte), pas une réponse JSON.

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>PIB — 2 pays — atlas</title>
<meta name="description" content="2 pays × 1 indicateurs, valeurs figées le 2026-09-09">
...
GET/api/chart/timeseries.svg

Graphique SVG autonome (une série, un pays), embarquable — gratuit, hors tunnel de paiement.

Paramètre
Type
Requis
Défaut
Description
indicator
str
oui
Code d'indicateur.
country
str
oui
Code pays.
start
int
non
Année de début, ge=1960.
end
int
non
Année de fin, le=2100.
color
str
non
couleur par défaut
Couleur hex ; retombe sur la couleur par défaut si invalide.
bg
str
non
fond par défaut
Couleur de fond hex ; retombe sur le fond par défaut si invalide.
grid
bool
non
true
Affiche la grille.
width
int
non
480
Largeur en pixels, ge=120, le=1600.
height
int
non
260
Hauteur en pixels, ge=90, le=1200.
Code
Erreur
Cas
404
unknown_indicator
Code d'indicateur inconnu.
404
unknown_country
Code pays inconnu.
CURL
curl "https://atlasfeed.fr/api/chart/timeseries.svg?indicator=NY.GDP.MKTP.CD&country=FRA" \
  -o pib-france.svg
PYTHON
import requests

r = requests.get(
    "https://atlasfeed.fr/api/chart/timeseries.svg",
    params={"indicator": "NY.GDP.MKTP.CD", "country": "FRA"},
)
open("pib-france.svg", "wb").write(r.content)
JAVASCRIPT
const img = document.createElement("img");
img.src = "https://atlasfeed.fr/api/chart/timeseries.svg?indicator=NY.GDP.MKTP.CD&country=FRA";
document.body.appendChild(img);
RÉPONSE
Contenu : image/svg+xml. En-tête Cache-Control: public, max-age=3600.
Note : cette route ne rend que du SVG — elle n'a pas de paramètre "format", et un
"?format=png" y serait simplement ignoré. Pour un PNG, passer par une capture :
GET /api/capture/{capture_id}?format=png (501 si l'extra "png" (CairoSVG) est absent
du déploiement).

<svg viewBox="0 0 480 260" width="480" height="260" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="PIB — France">
<text x="54" y="20" style="font:500 13px sans-serif;fill:#333">PIB — France</text>
<path d="M54 210 H460" stroke="#888" stroke-width="1" opacity="0.25"></path>
...
GET/api/chart/compare.svg

Graphique SVG autonome en barres — un pays par indicateur, à une année donnée (ou la dernière disponible). Gratuit, hors tunnel de paiement.

Paramètre
Type
Requis
Défaut
Description
countries
str
oui
Codes séparés par virgules, jusqu'à 5 pays.
indicator
str
oui
Code d'indicateur.
year
int
non
dernière année disponible
ge=1960, le=2100.
color, bg, grid, width, height
non
Identiques à timeseries.svg.
Code
Erreur
Cas
404
unknown_indicator
Code d'indicateur inconnu.
400
empty_countries_param
countries ne contient aucun code exploitable.
404
unknown_country
Un code pays fautif (un seul signalé, le premier trouvé).
Route coûteuse en calcul : soumise à la limite de 30 requêtes/minute par IP anonyme, en plus des limites communes — voir Démarrage.
CURL
curl "https://atlasfeed.fr/api/chart/compare.svg?countries=FRA,DEU&indicator=NY.GDP.MKTP.CD" \
  -o pib-comparaison.svg
PYTHON
import requests

r = requests.get(
    "https://atlasfeed.fr/api/chart/compare.svg",
    params={"countries": "FRA,DEU", "indicator": "NY.GDP.MKTP.CD"},
)
open("pib-comparaison.svg", "wb").write(r.content)
JAVASCRIPT
const img = document.createElement("img");
img.src = "https://atlasfeed.fr/api/chart/compare.svg?countries=FRA,DEU&indicator=NY.GDP.MKTP.CD";
document.body.appendChild(img);
RÉPONSE
Contenu : image/svg+xml.

<svg viewBox="0 0 480 260" width="480" height="260" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="PIB">
<text x="54" y="20" style="font:500 13px sans-serif;fill:#333">PIB</text>
<path d="M54 210.0 H460" stroke="#888" stroke-width="1" opacity="0.35"></path>
<rect x="94.6" y="96.7" width="...
GET/api/coverage

Ce qu'Atlas possède réellement, pays par pays — alimente le globe de couverture de l'accueil. Le dénominateur exclut les indicateurs dont la collecte a échoué et Data360 (échantillon extrapolé jeté, jamais compté).

Code
Erreur
Cas
503
coverage_unavailable
data/coverage.json n'a pas été fabriqué (script dédié) — fichier versionné donc présent en production, absence typique d'un dépôt fraîchement cloné.
CURL
curl "https://atlasfeed.fr/api/coverage"
PYTHON
import requests

r = requests.get("https://atlasfeed.fr/api/coverage")
print(r.json())
JAVASCRIPT
fetch("https://atlasfeed.fr/api/coverage")
  .then(r => r.json())
  .then(console.log);
RÉPONSE
{
  "fenetre": [2015, 2025],
  "denominateur": 691,
  "catalogue_total": 3708,
  "pays": {
    "ABW": {
      "total": 241, "part": 0.3488,
      "sources": [
        {"cle": "owid", "nom": "Our World in Data", "total": 147},
        {"cle": "worldbank", "nom": "World Bank", "total": 88},
        {"cle": "ember", "nom": "Ember", "total": 6}
      ]
    }
  }
}
Un pays sans aucune valeur (total: 0) est absent de "pays", jamais présent avec un zéro.
Quotas comptés par mois calendaire. Dépassement : réponse 429, jamais de facturation surprise. Voir Démarrage pour l'authentification et les erreurs communes