Développeurs

API RELATT — Diffusion v1

Une API de lecture, pensée pour vos serveurs : lisez les contenus de votre espace en JSON et rediffusez-les dans vos outils. Pour un affichage public sur une page web, utilisez plutôt les widgets.

L'API renvoie exactement les contenus visibles au magazine de votre espace — mêmes règles, mêmes données. Chaque clé est liée à un seul espace : une clé, votre espace. Une clé de réseau couvre le flux agrégé et l'annuaire de ses membres.

Sécurité

N'utilisez jamais votre clé dans du JavaScript exécuté par le navigateur : elle serait publiée. L'API v1 est faite pour vos serveurs. Pour afficher du contenu côté navigateur, utilisez les widgets.

Où obtenir une clé ? Sur la page Diffuser de votre espace (/magazine/votre-espace/diffuser) — bouton « Nouvelle clé ». La clé complète n'est affichée qu'une seule fois.

Authentification

Chaque requête porte votre clé dans l'en-tête Authorization, préfixée par Bearer :

HTTP
Authorization: Bearer rk_live_…

Pas de CORS. L'API n'est volontairement pas appelable depuis un navigateur : une clé exposée côté client est une clé compromise. Le navigateur, c'est le widget.

Démarrage rapide

Récupérez vos cinq derniers contenus (remplacez rk_live_… par votre clé) :

bash
curl -H "Authorization: Bearer rk_live_…" \
  "https://proto.relatt.it/api/v1/items?limit=5"

Endpoints

Quatre points d'entrée, tous en lecture (GET). L'espace est déterminé par la clé — aucun identifiant dans l'URL.

MéthodeEndpointDescription
GET/api/v1/relattIdentité de l'espace et statistiques.
GET/api/v1/itemsContenus visibles (filtrables, paginés).
GET/api/v1/rubricsRubriques éditoriales de l'espace.
GET/api/v1/membersMembres du réseau (réseaux uniquement).

Enveloppe. Les listes renvoient { data: [...], meta: { count, next_cursor } }. La pagination est par curseur (keyset), jamais par offset.

GET /api/v1/relatt

Identité de l'espace : slug, name, type (publisher ou network), description, logo_url, primary_color, magazine_url, et stats.items_by_type.

json
{
  "slug": "exemple",
  "name": "Exemple",
  "type": "publisher",
  "description": "Éditeur de contenu sur RELATT.",
  "logo_url": "https://exemple.ch/logo.svg",
  "primary_color": "#0d5c4a",
  "magazine_url": "https://proto.relatt.it/magazine/exemple",
  "stats": { "items_by_type": { "news": 42, "event": 12, "training": 5 } }
}

GET /api/v1/items

Les contenus visibles de l'espace. Tous les paramètres sont optionnels :

ParamètreTypeDescription
typescsvFiltre par type. Valeurs : news, event, training, job, publication, media, service, about, donation, other.
rubricslugFiltre par rubrique. Prime sur types si les deux sont fournis.
limitentierNombre d'éléments, de 1 à 100 (défaut 20).
cursorstringCurseur de pagination, fourni par meta.next_cursor.
sinceISO 8601Contenus datés à partir de cette date (sur published_at, collecte à défaut).
untilISO 8601Contenus datés jusqu'à cette date.
qstringRecherche plein texte sur le titre et le résumé.
memberslugRéseaux uniquement : ne renvoie que les contenus de ce membre.

Exemple de réponse (un contenu) :

json
{
  "data": [
    {
      "id": 4812,
      "type": "event",
      "title": "Portes ouvertes 2026",
      "summary": "Une journée pour découvrir nos activités.",
      "url": "https://exemple.ch/agenda/portes-ouvertes",
      "image_url": "https://exemple.ch/media/po.jpg",
      "published_at": "2026-06-30T00:00:00.000Z",
      "date_start": "2026-09-14T09:00:00.000Z",
      "date_end": "2026-09-14T17:00:00.000Z",
      "location": "Genève",
      "tags": ["portes-ouvertes", "public"],
      "attachment_url": null,
      "relatt": { "slug": "exemple", "name": "Exemple" }
    }
  ],
  "meta": { "count": 1, "next_cursor": "eyJ0cyI6IjIwMjYtMDYtMzAiLCJpZCI6NDgxMn0" }
}

Champs d'un contenu :

ChampTypeDescription
identierIdentifiant stable du contenu.
typestringL'un des 10 types éditoriaux.
titlestringTitre du contenu.
summarystringRésumé court.
urlstringLien canonique (site source ou page native du magazine).
image_urlstring | nullImage principale, si disponible.
published_atISO 8601Date de publication (ou de collecte à défaut).
date_startISO 8601 | nullDébut d'un événement ou d'une formation.
date_endISO 8601 | nullFin d'un événement ou d'une formation.
locationstring | nullLieu, selon le type.
tagsstring[]Étiquettes du contenu.
attachment_urlstring | nullPDF principal éventuel.
relatt{ slug, name }Émetteur du contenu (≠ l'espace interrogé pour un réseau).

Pagination — enchaîner les pages avec meta.next_cursor :

bash
# Première page
curl -H "Authorization: Bearer rk_live_…" \
  "https://proto.relatt.it/api/v1/items?limit=20"

# Page suivante : reprendre meta.next_cursor
curl -H "Authorization: Bearer rk_live_…" \
  "https://proto.relatt.it/api/v1/items?limit=20&cursor=eyJ0cyI6IjIwMjYtMDYtMzAiLCJpZCI6NDgxMn0"

GET /api/v1/rubrics

Les rubriques éditoriales de l'espace, chacune avec son slug, son label, sa description et les content_types qu'elle regroupe.

json
{
  "data": [
    {
      "slug": "agenda",
      "label": "Agenda",
      "description": "Les événements à venir.",
      "content_types": ["event"]
    }
  ]
}

GET /api/v1/members

Réseaux uniquement (sinon 403) : les membres approuvés du réseau, avec leur nombre de contenus et le lien vers leur magazine.

json
{
  "data": [
    {
      "slug": "membre-un",
      "name": "Membre Un",
      "description": "Un membre du réseau.",
      "url": "https://membre-un.ch",
      "logo_url": "https://membre-un.ch/logo.png",
      "items_count": 37,
      "magazine_url": "https://proto.relatt.it/magazine/membre-un"
    }
  ]
}

Erreurs & limites

Les erreurs suivent la forme standard H3 : { statusCode, statusMessage }.

json
{
  "statusCode": 401,
  "statusMessage": "Clé API manquante ou invalide"
}
CodeSensCause typique
400Paramètre invalideType inconnu, limit hors bornes, date mal formée…
401AuthentificationClé absente, invalide ou révoquée.
403PortéeScope insuffisant, ou endpoint réservé à un type d'espace (ex. /members hors réseau).
404IntrouvableRessource inexistante (rubrique ou membre inconnu).
429Quota dépasséTrop de requêtes. En-tête Retry-After (en secondes).

Débit. Chaque clé est limitée à 120 requêtes / minute, avec une tolérance de rafale de 30 requêtes / 5 s. Au-delà : 429 avec un en-tête Retry-After indiquant le délai d'attente en secondes.

Widgets

Pour un affichage public, embarquez un widget : deux lignes à coller, sans clé API. Le token (emb_…) s'obtient sur la page Diffuser de votre espace.

Recommandé — le script ajuste la hauteur automatiquement :

html
<!-- Recommandé : hauteur automatique -->
<div data-relatt-embed="emb_a1b2c3d4e5f6"></div>
<script async src="https://proto.relatt.it/embed.js"></script>

Simple — iframe seule, hauteur fixe :

html
<!-- Simple : iframe seule, hauteur fixe -->
<iframe src="https://proto.relatt.it/embed/emb_a1b2c3d4e5f6"
        style="width:100%;border:0;" height="600" loading="lazy"
        title="Actualités — Nom de l'espace"></iframe>

Bonnes pratiques

  • Mettez en cache les réponses côté client 1 à 5 minutes : le contenu est digéré, pas temps réel.
  • Une clé par intégration (site, application, intranet) — vous en révoquez une sans casser les autres.
  • Révoquez immédiatement une clé compromise depuis la page Diffuser : l'effet est instantané.
  • N'exposez jamais une clé côté navigateur — pour l'affichage public, un widget suffit.

Envie de comprendre l'offre et les formules ? Voir la page Diffusion →