API publique du Codex ligérien
L’API expose les index éditoriaux publiés du Codex ligérien. Elle est
publique, anonyme, gratuite et en lecture seule : aucune clé ni aucun
header d’autorisation n’est nécessaire. Les réponses utilisent JSON sur HTTPS,
la version actuelle se trouve sous /api/v1 et ne propose pas de pagination.
Démarrage rapide#
URL de base de production :
https://codex.loireridezen.bikePremier appel, sans autre dépendance que curl :
curl --fail-with-body \
https://codex.loireridezen.bike/api/v1/indexesRésultat attendu :
- statut
200; Content-Type: application/json; charset=utf-8;- collection des index dans
body.data; - aucun token ou compte nécessaire.
Continuez ensuite avec la collection Faune :
curl --fail-with-body \
https://codex.loireridezen.bike/api/v1/indexes/faune/entriesPour tester la même route sur le projet local :
curl --fail-with-body \
http://localhost:3000/api/v1/indexesLicences en bref. Les textes et données sont réutilisables sous CC BY-NC-SA 4.0 avec attribution. Les illustrations personnalisées, logos et éléments de marque restent tous droits réservés. La présence d’une
media.imageUrlne constitue pas une autorisation de reproduction.
Parcours conseillé#
Le contrat OpenAPI décrit exhaustivement les paramètres, schémas, contraintes et headers.
Pour une intégration TypeScript ou React Native/Expo, utilisez le guide du SDK officiel. La présente page reste la référence du contrat HTTP ; le guide SDK documente le client typé qui l’encapsule.
1. Découvrir l’API#
GET /api/v1 — identité de l’API, licences et liens de découverte.
- paramètres : aucun ;
- succès :
200; - OpenAPI : opération
getApiRoot.
curl --fail-with-body \
https://codex.loireridezen.bike/api/v12. Lister les index publiés#
GET /api/v1/indexes — collection complète des index actuellement publiés.
- paramètres : aucun ;
- succès :
200; - OpenAPI : opération
listIndexes.
curl --fail-with-body \
https://codex.loireridezen.bike/api/v1/indexes3. Lire un index#
GET /api/v1/indexes/{index} — présentation et métadonnées d’un index.
- paramètre
index: slug de l’index, par exemplefaune; - succès :
200; - OpenAPI : opération
getIndex.
curl --fail-with-body \
https://codex.loireridezen.bike/api/v1/indexes/faune4. Lister les entrées d’un index#
GET /api/v1/indexes/{index}/entries — collection complète des entrées de
l’index, sans pagination dans la V1.
- paramètre
index: slug d’un index publié ; - succès :
200; - OpenAPI : opération
listIndexEntries.
curl --fail-with-body \
https://codex.loireridezen.bike/api/v1/indexes/faune/entries5. Lire une entrée#
GET /api/v1/indexes/{index}/entries/{slug} — détail d’une entrée publique.
- paramètre
index: slug de l’index ; - paramètre
slug: slug de l’entrée dans cet index ; - succès :
200; - OpenAPI : opération
getIndexEntry.
curl --fail-with-body \
https://codex.loireridezen.bike/api/v1/indexes/faune/entries/heron-cendreHEAD et OPTIONS#
Chaque route publique accepte également :
HEAD, qui retourne le même statut et les mêmes headers pertinents queGET, mais sans corps ;OPTIONS, qui retourne204, les méthodes autorisées et les headers CORS.
Les méthodes publiques sont GET, HEAD et OPTIONS.
Exemples curl#
Les cinq appels du parcours précédent sont directement copiables.
Pour afficher aussi le statut et les headers :
curl -i \
https://codex.loireridezen.bike/api/v1/indexes/faunePour observer volontairement une réponse 404 :
curl -i \
https://codex.loireridezen.bike/api/v1/indexes/faune/entries/inconnuCette dernière réponse utilise
application/problem+json; charset=utf-8. Testez toujours le statut avant de
traiter le corps comme une enveloppe de succès.
JavaScript#
L’exemple suivant utilise uniquement fetch. Il vérifie response.ok,
transforme un problème HTTP en erreur et ne télécharge aucune illustration.
Le fichier exécutable est disponible dans
examples/quickstart.js.
const baseUrl = "https://codex.loireridezen.bike";
async function main() {
const response = await fetch(`${baseUrl}/api/v1/indexes/faune/entries`);
const body = await response.json();
if (!response.ok) {
throw new Error(`${body.status} ${body.title}: ${body.detail}`);
}
for (const entry of body.data) {
const mediaStatus =
entry.media.imageUrl === null
? "sans illustration"
: "illustration disponible — droits réservés";
console.log(`${entry.name} (${entry.slug}) — ${mediaStatus}`);
}
}
main().catch((error) => {
console.error(error);
if (typeof process !== "undefined") process.exitCode = 1;
});Compatible avec les navigateurs modernes et les versions récentes de Node.js :
node docs/api/examples/quickstart.jsTypeScript#
Les types ci-dessous sont volontairement minimaux. Les types exhaustifs, les
enums et les contraintes restent définis dans OpenAPI. Le fichier complet est
disponible dans
examples/quickstart.ts.
type PublicLicenses = {
content: {
id: string;
name: string;
url: string;
attribution: string;
};
media: {
name: string;
copyright: string;
reuseAllowed: false;
};
};
type ApiEnvelope<T> = {
apiVersion: "1";
data: T;
meta: { license: PublicLicenses };
links: Record<string, string>;
};
type PublicEntry = {
id: string;
index: "faune" | "flore" | "chateaux";
slug: string;
name: string;
subtitle: string;
summary: string | null;
media: {
emoji: string;
imageUrl: string | null;
};
attributes: Record<string, unknown>;
};
type Problem = {
type: string;
title: string;
status: number;
detail: string;
instance: string;
};
const baseUrl = "https://codex.loireridezen.bike";
async function main() {
const response = await fetch(`${baseUrl}/api/v1/indexes/faune/entries`);
const body = (await response.json()) as
ApiEnvelope<PublicEntry[]> | Problem;
if (!response.ok) {
const problem = body as Problem;
throw new Error(
`${problem.status} ${problem.title}: ${problem.detail}`,
);
}
const envelope = body as ApiEnvelope<PublicEntry[]>;
for (const entry of envelope.data) {
const mediaStatus =
entry.media.imageUrl === null
? "sans illustration"
: "illustration disponible — droits réservés";
if (entry.index === "faune") {
const scientificName = entry.attributes.nomScientifique;
console.log(
entry.name,
typeof scientificName === "string"
? scientificName
: "(nom scientifique non renseigné)",
mediaStatus,
);
} else {
console.log(entry.name, mediaStatus);
}
}
const collectionUrl = new URL(envelope.links.self, baseUrl);
console.log(`Collection : ${collectionUrl}`);
}
main().catch((error: unknown) => {
console.error(error);
process.exitCode = 1;
});
export {};index sert de discriminateur avant d’interpréter les attributs spécialisés.
attributes varie selon l’index ; summary et media.imageUrl peuvent être
null. TypeScript aide le consommateur, mais ne valide pas une donnée qui
traverse le réseau : une validation runtime reste utile. Aucun client n’est
généré dans cette version.
Modèle de données#
Enveloppe de succès#
Toutes les réponses de succès partagent quatre propriétés :
| Champ | Rôle |
|---|---|
apiVersion | Version majeure de l’API, actuellement "1" |
data | Ressource ou collection demandée |
meta.license | Licences applicables aux données et aux médias |
links | Liens relatifs permettant de poursuivre le parcours |
Les liens sont des chemins relatifs à résoudre avec l’URL de base :
const resourceUrl = new URL(body.links.self, baseUrl);Index public#
Un index expose :
slug,label,titleetdescriptionpour l’identifier ;marketaccentpour sa présentation ;presentationetpresentationMarkdownpour son introduction ;state,entryCountetupdatedAtpour son état public ;source,corridoreteditorialWarningpour son contexte éditorial ;links.selfetlinks.entriespour la navigation.
editorialWarning peut être null. Seuls les index publiés sont exposés. Un
index en relecture répond comme un index inconnu.
Entrée publique#
Le socle commun d’une entrée contient :
id, identifiant stable composé comme<index>:<slug>;index, discriminateur de la variante ;slug, identifiant de route à l’intérieur de l’index ;name,subtitleetsummary, cette dernière pouvant êtrenull;media.emojietmedia.imageUrl, cette dernière pouvant êtrenull;attributes, objet dont la structure dépend deindex.
Les variantes actuellement publiées sont :
faune: taxonomie, identification, conservation, rareté et milieu ;flore: catégorie, taxonomie, statut, floraison, rareté et milieu ;chateaux: localisation, coordonnées, époque, protection, renommée et visite.
Consultez le
schéma PublicEntry dans OpenAPI
pour les propriétés et contraintes exhaustives.
Médias#
emoji est une représentation textuelle. imageUrl peut être null.
Attention — illustrations protégées. Une URL présente n’accorde aucun droit de reproduction. Vérifiez
meta.license.mediaet demandez une autorisation écrite avant d’intégrer une illustration personnalisée de Loire Ride Zen.
Erreurs#
Les erreurs utilisent :
application/problem+json; charset=utf-8Leur structure suit Problem Details :
| Champ | Rôle |
|---|---|
type | URI identifiant la famille du problème |
title | Titre stable |
status | Statut HTTP |
detail | Explication destinée au développeur |
instance | Chemin de la requête ayant rencontré le problème |
| ::: |
Exemple complet :
{
"type": "https://codex.loireridezen.bike/problems/not-found",
"title": "Resource not found",
"status": 404,
"detail": "No published entry matches the requested identifier.",
"instance": "/api/v1/indexes/faune/entries/inconnu"
}Une 404 désigne une ressource inconnue ou non publiée. Les erreurs ne
contiennent pas de stack technique et utilisent Cache-Control: no-store. Une
erreur 500 reste volontairement générique.
CORS et cache#
- les lectures cross-origin utilisent
Access-Control-Allow-Origin: *; - les credentials ne sont ni nécessaires, ni annoncés par le contrat ;
- les méthodes publiques sont
GET,HEADetOPTIONS; - les réponses de succès peuvent être mises en cache ;
- le consommateur doit respecter le
Cache-Controlreçu ; - les erreurs ne doivent pas être mises en cache.
OpenAPI et Bruno documentent et vérifient les valeurs exactes des headers.
Attribution et licences#
Textes et données#
Les textes et données sont sous CC BY-NC-SA 4.0. Toute réutilisation doit créditer l’auteur, indiquer les modifications, rester non commerciale et partager les adaptations sous la même licence.
Attribution prête à copier :
Données : Julien Julien — Loire Ride Zen, sous licence CC BY-NC-SA 4.0.
Source : https://codex.loireridezen.bike/api/v1Si les données sont adaptées :
Données adaptées de Julien Julien — Loire Ride Zen, sous licence CC BY-NC-SA 4.0. Modifications : [description].Illustrations et identité visuelle#
© 2026 Julien Julien — Loire Ride Zen. Tous droits réservés.L’exposition d’une illustration par media.imageUrl ne constitue pas une
autorisation de reproduction, modification, redistribution ou utilisation
commerciale. Demandez une autorisation écrite préalable avant toute
intégration.
Code et documentation#
Le code source et la documentation technique sont distribués sous licence MIT, sous réserve des exclusions détaillées dans la licence des contenus.
OpenAPI et Bruno#
Ces trois outils sont complémentaires :
- ce guide développeur fournit le démarrage et les concepts essentiels ;
- OpenAPI décrit le contrat exhaustif et peut être importé dans un client compatible ;
- Bruno fournit des requêtes prêtes à exécuter en local ou en production.
Après import d’OpenAPI, remplacez le serveur de production par
http://localhost:3000 pour explorer une instance locale.
Développement local et source#
Lancez le projet :
pnpm install
pnpm devPuis ouvrez :
http://localhost:3000/docs/apiLa source canonique de cette page et les exemples exécutables se trouvent dans
le
dossier docs/api.
Pour vérifier la documentation avant contribution :
pnpm api:docs:check