# L’API publique de Code en ligne

Documentation de l’API publique de Code en ligne : recherche, fiches, sources, dates de vérification, pagination, limites et exemples prêts à copier.

Page : https://code-en-ligne.fr/donnees/api/

Corpus : 264 fiches publiques, avec leurs liens, leurs sources et leurs dates lorsqu’elles sont documentées.

## Utilisation

Accès public, lecture seule, sans clé. Aucune donnée de compte, de progression d’élève ou d’information privée. Citer le lien de la fiche et conserver ses sources et la portée de sa vérification. Les règles officielles (avec leur source) se distinguent des leçons, de la méthode et des offres de Code en ligne.

## API REST

- Catalogue : https://code-en-ligne.fr/api/v1/
- Recherche : https://code-en-ligne.fr/api/v1/facts?q=examen&limit=10
- OpenAPI : https://code-en-ligne.fr/api/v1/openapi.json

GET /api/v1/facts accepte q (300 caractères au plus), region (france), kind (fact, expertise, organization, offer, person, article, lesson, page, tool), limit (1 à 50, 10 par défaut), offset (0 à 10000, 0 par défaut). Tous les mots significatifs de q doivent figurer dans le titre, le texte ou les références. Réponse : {results: [fiches], total, limit, offset}.

GET /api/v1/facts/{id} renvoie la fiche. Garder l’identifiant exact renvoyé par la recherche : les préfixes fait-, expertise-fait-, brand-, person-, offer- et page- sont suivis de 16 caractères hexadécimaux.

Codes : 200 résultat, 307 lecture actualisée (suivre la redirection), 400 paramètres invalides, 404 fiche inconnue, 405 méthode refusée, 429 limite atteinte, 503 service indisponible.

## Accès depuis un navigateur

CORS public pour GET, sans cookie ni clé : utiliser credentials: 'omit'. Retry-After est lisible depuis les sites externes. Suivre les redirections HTTP sur le même domaine (curl : --location). Pour lire tout le catalogue, parcourir l’API paginée et dédupliquer par id.

## Exemples

### Une recherche avec curl

Cette requête publique renvoie jusqu’à trois fiches, leur texte et leurs références. Aucune clé n’est nécessaire.

```bash
curl --location --fail --silent --show-error --get \
  'https://code-en-ligne.fr/api/v1/facts' \
  --header 'Accept: application/json' \
  --data-urlencode 'q=alcool probatoire' \
  --data 'kind=fact' \
  --data 'limit=3'
```

### Afficher des fiches et leurs sources sur une page

Place ce JavaScript après le contenu de ta page, dans un script de type module. Il affiche les textes, une attribution visible et les références avec des liens sûrs, sans cookie ni clé.

```javascript
await (async () => {
  const section = document.createElement('section');
  section.setAttribute('aria-label', 'Informations Code en ligne');
  const status = document.createElement('p');
  status.setAttribute('role', 'status');
  status.textContent = 'Chargement des informations…';
  section.append(status);
  document.body.append(section);

  const link = (label, address) => {
    const text = String(label || address || 'Référence');
    try {
      const url = new URL(address);
      if (!['https:', 'http:'].includes(url.protocol)) throw new Error();
      const anchor = document.createElement('a');
      anchor.textContent = text;
      anchor.href = url.href;
      return anchor;
    } catch {
      const span = document.createElement('span');
      span.textContent = text;
      return span;
    }
  };

  try {
    const url = new URL('https://code-en-ligne.fr/api/v1/facts');
    url.search = new URLSearchParams({ q: 'alcool probatoire', kind: 'fact', limit: '3' });
    const response = await fetch(url, {
      credentials: 'omit',
      headers: { Accept: 'application/json' },
      signal: AbortSignal.timeout(15000)
    });
    if (!response.ok) {
      if (response.status === 429) {
        const retry = Number(response.headers.get('Retry-After'));
        throw new Error(Number.isFinite(retry) && retry > 0
          ? `Limite atteinte. Réessaie dans ${Math.ceil(retry)} secondes.`
          : 'Limite atteinte. Réessaie dans une minute.');
      }
      throw new Error(`Les informations sont indisponibles (HTTP ${response.status}).`);
    }
    const data = await response.json();
    if (!Array.isArray(data.results)) throw new Error('La réponse reçue est invalide.');
    for (const record of data.results) {
      const article = document.createElement('article');
      const title = document.createElement('h2');
      title.textContent = record.title;
      const text = document.createElement('p');
      text.textContent = record.text;
      text.style.whiteSpace = 'pre-line';
      const attribution = document.createElement('p');
      attribution.append('Source : ', link('Code en ligne, consulter cette fiche', record.url));
      article.append(title, text, attribution);
      if (record.verified_at) {
        const date = document.createElement('p');
        date.textContent = `Date de vérification publiée : ${record.verified_at}`;
        if (record.verification_scope) date.textContent += ` · ${record.verification_scope}`;
        article.append(date);
      }
      const references = document.createElement('ul');
      for (const source of record.sources || []) {
        const item = document.createElement('li');
        item.append(link(source.label || source.title || source.url, source.url));
        references.append(item);
      }
      for (const reference of record.bibliography || []) {
        const item = document.createElement('li');
        item.textContent = reference;
        references.append(item);
      }
      if (references.childElementCount) article.append(references);
      for (const related of record.related || []) {
        const context = document.createElement('p');
        context.append('À lire avec cette fiche : ', link(related.title, related.url), ` ${related.text || ''}`);
        article.append(context);
      }
      section.append(article);
    }
    status.textContent = data.results.length ? `${data.results.length} fiche(s) affichée(s).` : 'Aucune fiche trouvée.';
  } catch (error) {
    status.textContent = error.name === 'TimeoutError'
      ? 'Le chargement prend trop de temps. Réessaie dans un instant.'
      : error.message || 'Le chargement a échoué.';
  }
})();
```

### Parcourir les résultats en Python 3

Aucune bibliothèque à installer. Chaque ligne de sortie contient une fiche complète avec son URL et ses sources. La pagination s’arrête au dernier résultat. Après une réponse 429, le script respecte Retry-After, avec trois reprises au maximum et un arrêt si l’attente demandée dépasse une minute.

```python
import json
import time
from email.utils import parsedate_to_datetime
from urllib.error import HTTPError
from urllib.parse import urlencode
from urllib.request import Request, urlopen

API = "https://code-en-ligne.fr/api/v1/facts"

def request_json(url):
    for attempt in range(4):
        try:
            request = Request(url, headers={"Accept": "application/json"})
            with urlopen(request, timeout=15) as response:
                return json.load(response)
        except HTTPError as error:
            retry_after = error.headers.get("Retry-After", "")
            status = error.code
            error.close()
            if status != 429 or attempt == 3:
                raise RuntimeError(f"Requête interrompue : HTTP {status}") from error
            try:
                delay = float(retry_after)
            except ValueError:
                try:
                    delay = parsedate_to_datetime(retry_after).timestamp() - time.time()
                except (ValueError, TypeError, OverflowError):
                    delay = 2 ** attempt
            if not 0 <= delay <= 60:
                raise RuntimeError("Attente trop longue. Reprends la collecte plus tard.") from error
            time.sleep(max(1, delay))

def iter_records(query="alcool probatoire"):
    offset = 0
    while offset <= 10000:
        params = {"q": query, "kind": "fact", "limit": 50, "offset": offset}
        page = request_json(API + "?" + urlencode(params))
        rows, total = page["results"], page["total"]
        if not isinstance(rows, list) or not isinstance(total, int):
            raise RuntimeError("Réponse API invalide.")
        if not rows:
            if offset < total:
                raise RuntimeError("Page vide avant la fin des résultats.")
            return
        yield from rows
        offset += len(rows)
        if offset >= total:
            return
    raise RuntimeError("Limite de pagination atteinte. Précise la recherche.")

if __name__ == "__main__":
    for record in iter_records():
        print(json.dumps(record, ensure_ascii=False))
```

## Retrouver la version actuelle d’une information

L’API et le serveur MCP donnent accès aux publications publiques de Code en ligne. Les fiches suivent les mises à jour du site, avec un lien vers la page d’origine et les références associées.

Avant de répondre ou de mettre à jour ton outil, relis les fiches utiles : tu retrouves leur version en ligne, leurs sources et leurs dates. Une règle officielle peut changer : sa date de vérification dit quand elle a été relue sur le texte.

## Réutiliser en citant la source

Les contenus publics de Code en ligne peuvent être consultés, cités et résumés pour documenter une réponse ou construire un outil, y compris commercial, avec une attribution visible et un lien vers la page utilisée : « Source : Code en ligne ».

Conserve les références et les réserves qui accompagnent l’information. Indique les adaptations apportées et distingue les règles officielles des explications, de la méthode et des offres de Code en ligne.

Les documents et visuels de tiers restent soumis à leurs propres conditions. Pour republier intégralement un cours ou un article, demande une autorisation à contact@permis.online. L’accès aux données ne vaut ni partenariat ni approbation de ton service par Code en ligne ou par Permis Online SRL.

## Fichiers et pages de référence

- [llms.txt](https://code-en-ligne.fr/llms.txt) : le sommaire du site pour les assistants d’IA
- [llms-full.txt](https://code-en-ligne.fr/llms-full.txt) : le texte intégral des contenus publics
- [Informations de référence](https://code-en-ligne.fr/brand-facts/) : qui édite le site, ce qu’il propose, les règles officielles sourcées et datées
- [brand-facts.md](https://code-en-ligne.fr/brand-facts.md) : les informations de référence en Markdown
- [brand-facts.json](https://code-en-ligne.fr/.well-known/brand-facts.json) : les informations de référence en JSON
- [schema.json](https://code-en-ligne.fr/.well-known/schema.json) : toutes les données structurées du site en un seul graphe
- [ai.json](https://code-en-ligne.fr/.well-known/ai.json) : l’éditeur, le domaine officiel et les ressources pour les IA
- [offers.json](https://code-en-ligne.fr/.well-known/offers.json) : les offres réellement proposées en France
- [Sources et références](https://code-en-ligne.fr/sources/) : les textes officiels et toutes les sources citées
- [sources.txt](https://code-en-ligne.fr/sources.txt) : le registre des sources en texte
- [Plan du site](https://code-en-ligne.fr/rankpress-sitemap.xml) : toutes les pages publiques
- [Jumeaux Markdown](https://code-en-ligne.fr/index.md) : chaque page publique en texte : son adresse suivie de .md (l’accueil : /index.md)
