celyn Culture API — Documentation
Référence des endpoints de la verticale culture
Les verticales actu et sport sont servies sur celyn.io avec la même clé, mais une clé créée ici ne les ouvre pas d'office : /api/sport/* et /api/news/* répondent 403 tant que le scope actu n'a pas été activé sur la clé. Accès sur demande.
Authentication
Include your API key in every request header:
x-api-key: ck_your_api_key_here
Base URL
Rate Limits
1,000 requests per hour per API key.
Headers included in every response (per-instance, approximate — celyn.io runs behind a load balancer, so these count against whichever server handled the request, not a global total):
X-RateLimit-Limit
X-RateLimit-Remaining
X-RateLimit-Reset
Error Responses
| Status | Meaning | Example Body |
|---|---|---|
| 400 | Bad request | { "error": "q parameter is required" } |
| 401 | Missing/invalid API key | { "error": "Missing API key in x-api-key header" } |
| 404 | Not found | { "error": "Oeuvre not found" } |
| 422 | Validation error | { "error": "Invalid date format for 'from'" } |
| 429 | Rate limited | { "error": "Rate limit exceeded" } + Retry-After header |
| 500 | Server error | { "error": "Internal Server Error" } |
Couverture des données
Relevé du 2026-09-24, arrondi à la baisse. Les chiffres en direct sont sur la page d'accueil et le détail par type sur /dataviz.
Œuvres par type
| Expositions | 28 200+ |
| Concerts | 19 100+ |
| Films | 12 700+ |
| Livres | 10 300+ |
| Titres musicaux | 6 000+ |
| Séries TV | 3 900+ |
| Pièces de théâtre | 3 700+ |
| Albums | 3 500+ |
| Jeux vidéo | 3 200+ |
| Festivals | 1 600+ |
Lieux. Plus de 64 800 lieux (cinémas, théâtres, salles de concert, musées, festivals, bars et restaurants).
Événements. Plus de 17 100 événements à venir référencés à cette date, dans tous les types (concerts, théâtre, musées, cinéma, festivals, ateliers, littérature).
Géographie. France, avec une couverture plus dense dans les grandes villes : Paris, Nantes, Toulouse, Marseille, Bordeaux, Lyon, Rennes, Lille, Bayonne, Nice. Hors de ces zones, la couverture dépend des sources locales et peut être partielle : vérifiez sur votre territoire avant de vous engager.
Fraîcheur. Les événements et séances sont réingérés en continu (plusieurs fois par jour) ; les fiches œuvres sont enrichies chaque nuit. Le champ syncAt des listes et les paramètres since et cursor de /api/events permettent une synchronisation incrémentale.
Exemples d'intégration
Le même appel (événements autour de Paris) en trois langages. Remplacez YOUR_KEY par votre clé (créée gratuitement dans le portail).
curl
curl -H "x-api-key: YOUR_KEY" \ "https://celyn.io/api/events?lat=48.8566&lng=2.3522&radius_km=10&limit=5"
JavaScript / TypeScript (fetch)
const res = await fetch(
"https://celyn.io/api/events?lat=48.8566&lng=2.3522&radius_km=10&limit=5",
{ headers: { "x-api-key": process.env.CELYN_API_KEY } },
);
if (!res.ok) throw new Error(`celyn API ${res.status}`);
const { data, count } = await res.json();
console.log(count, data[0].title, data[0].venue?.city);
Swift (CelynKit)
import CelynKit
let client = CultureAPIClient(apiKey: "YOUR_KEY") // base URL: https://celyn.io/api
let page = try await client.events.list(.init(
lat: 48.8566, lng: 2.3522, radiusKm: 10, limit: 5
))
for event in page.data {
print(event.title, event.startTime, event.venue?.name ?? "-")
}
// Any endpoint, decoded into your own model:
struct MyOeuvre: Decodable { let id: String; let title: String }
let oeuvre: MyOeuvre = try await client.get("oeuvres/UUID")
CelynKit est le package Swift utilisé par l'application Keskonfé (iOS 17+, SPM). Il n'est pas encore publié sur un dépôt public : écrivez-nous pour l'obtenir. Il décode les dates ISO 8601 et convertit snake_case en camelCase pour vous.
Pas de SDK JavaScript publié pour l'instant : utilisez fetch comme ci-dessus, ou générez un client depuis openapi.json.
Events
/api/events
List events with optional geo, date, and category filters
Parameters
| lat | number | Latitude for geo search |
| lng | number | Longitude for geo search |
| radius_km | number | Search radius in km (default: 20) |
| from | string | Start date (ISO 8601) |
| to | string | End date (ISO 8601) |
| category | string | Oeuvre type: film, play, concert, etc. |
| topic | string | Filter by topic keyword(s) |
| age_min | number | Minimum recommended age |
| age_max | number | Maximum recommended age |
| grade | string | School grade filter — maternelle: PS, MS, GS; primaire: CP, CE1, CE2, CM1, CM2; collège: 6eme→3eme; lycée: seconde, premiere, terminale |
| limit | number | Max results (default: 50, max: 200) |
| offset | number | Pagination offset |
Example
curl -H "x-api-key: YOUR_KEY" \ "https://celyn.io/api/events?lat=43.3&lng=5.4&radius_km=10&from=2026-04-01&limit=5"
Response
{
"data": [
{
"id": "3f0c9a52-6f1d-4c1e-9d55-0a1b2c3d4e5f",
"title": "Titre d'exemple",
"category": "cinema",
"description": null,
"imageUrl": null,
"image": {
"url": null,
"sourceUrl": null,
"status": "unavailable"
},
"sourceUrl": null,
"ticketUrl": null,
"startTime": "2026-10-03T20:30:00.000Z",
"endTime": null,
"price": 9.5,
"isFree": 0,
"occasion": null,
"buyUrl": null,
"isSoldOut": 0,
"ticketsCheckedAt": null,
"isActive": 1,
"createdAt": "2026-09-20T08:00:00.000Z",
"updatedAt": "2026-09-21T08:00:00.000Z",
"syncUpdatedAt": "2026-09-21T08:00:00.000Z",
"mentionCount": 0,
"festivalEditionId": null,
"festival": null,
"_links": {
"recommendations": "/api/recommendations/b2a4c6e8-1357-4bdf-a024-68ace02468bd",
"similar": "/api/oeuvres/b2a4c6e8-1357-4bdf-a024-68ace02468bd/similar",
"opinions": "/api/oeuvres/b2a4c6e8-1357-4bdf-a024-68ace02468bd/opinions"
},
"curriculumTags": null,
"venue": {
"id": "7b1e2d90-4a6c-4f0e-8c21-5d6e7f8a9b0c",
"supabaseId": null,
"name": "Cinéma Exemple",
"address": "1 rue de l'Exemple",
"city": "Paris",
"latitude": 48.8566,
"longitude": 2.3522,
"venueType": "cinema",
"website": null
},
"oeuvre": {
"id": "b2a4c6e8-1357-4bdf-a024-68ace02468bd",
"title": "Titre d'exemple",
"originalTitle": null,
"oeuvreType": "film",
"year": 2025,
"director": "Nom Réalisateur",
"author": null,
"description": "Synopsis d'exemple.",
"genres": [
"drame"
],
"imageUrl": null,
"duration": 112,
"publisher": null,
"isbn": null,
"updatedAt": "2026-09-20T08:00:00.000Z",
"topics": null,
"ageMin": null,
"ageMax": null
},
"series": null
}
],
"count": 1,
"syncAt": "2026-09-24T10:00:00.000Z",
"isDelta": false,
"nextCursor": null,
"hasMore": false
}
/api/events/series
List recurring event series (same oeuvre, multiple showings)
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/events/series"
Response
{ "data": [{ "id": "uuid", "title": "Anora", "occurrenceCount": 3 }] }
/api/events/suppressed
List suppressed events (duplicate/expired/cancelled/invalid) with reason
Parameters
| limit | number | Max results |
| offset | number | Pagination offset |
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/events/suppressed"
Response
{ "data": [{ "id": "uuid", "suppressedAt": "...", "reason": "duplicate" }] }
/api/events/submissions
Submit a user-suggested event for review
Parameters
| body | json | Request body (JSON) |
Example
curl -X POST -H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "title": "...", "category": "concert", "venue_name": "...", "lat": 48.88, "lng": 2.34, "start_time": "2026-12-31T20:00:00Z", "device_id_hash": "<64 hex>" }' \
"https://celyn.io/api/events/submissions"
Response
{ "id": "uuid", "status": "pending" }
/api/events/:id
Get a single event with venue and oeuvre
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/events/UUID"
Response
{
"id": "3f0c9a52-6f1d-4c1e-9d55-0a1b2c3d4e5f",
"title": "Titre d'exemple",
"category": "cinema",
"description": null,
"imageUrl": null,
"image": {
"url": null,
"sourceUrl": null,
"status": "unavailable"
},
"sourceUrl": null,
"ticketUrl": null,
"startTime": "2026-10-03T20:30:00.000Z",
"endTime": null,
"price": 9.5,
"isFree": 0,
"occasion": null,
"buyUrl": null,
"isSoldOut": 0,
"ticketsCheckedAt": null,
"isActive": 1,
"createdAt": "2026-09-20T08:00:00.000Z",
"updatedAt": "2026-09-21T08:00:00.000Z",
"syncUpdatedAt": "2026-09-21T08:00:00.000Z",
"mentionCount": 0,
"festivalEditionId": null,
"festival": null,
"_links": {
"recommendations": "/api/recommendations/b2a4c6e8-1357-4bdf-a024-68ace02468bd",
"similar": "/api/oeuvres/b2a4c6e8-1357-4bdf-a024-68ace02468bd/similar",
"opinions": "/api/oeuvres/b2a4c6e8-1357-4bdf-a024-68ace02468bd/opinions"
},
"venue": {
"id": "7b1e2d90-4a6c-4f0e-8c21-5d6e7f8a9b0c",
"supabaseId": null,
"name": "Cinéma Exemple",
"address": "1 rue de l'Exemple",
"city": "Paris",
"latitude": 48.8566,
"longitude": 2.3522,
"venueType": "cinema",
"website": null
},
"oeuvre": {
"id": "b2a4c6e8-1357-4bdf-a024-68ace02468bd",
"title": "Titre d'exemple",
"originalTitle": null,
"oeuvreType": "film",
"year": 2025,
"director": "Nom Réalisateur",
"author": null,
"description": "Synopsis d'exemple.",
"genres": [
"drame"
],
"imageUrl": null,
"duration": 112,
"publisher": null,
"isbn": null,
"updatedAt": "2026-09-20T08:00:00.000Z"
},
"series": null
}
Venues
/api/venues
List venues with optional geo or city filter
Parameters
| lat | number | Latitude for geo search |
| lng | number | Longitude for geo search |
| radius_km | number | Search radius in km (default: 20) |
| city | string | Filter by city name |
| limit | number | Max results (default: 50, max: 200) |
| offset | number | Pagination offset |
| include | string | beta · sur demande (scope establishment) establishment → adds `establishment` {kind, accessibility, erp, capacity, sources[]} (beta, key scope 'establishment' on request, else 403). Weak ETag + Cache-Control: private, max-age=3600. Credit each sources[] entry (licence + observedAt) when redistributing. |
| accessible | boolean | beta · sur demande (scope establishment) true → only venues whose entrance is accessible per Acceslibre (fact confidence >= 0.70). Scope 'establishment'. |
| erp_type | string | beta · sur demande (scope establishment) Comma-separated ERP type letters (e.g. L,Y). Partial fact (Paris: Préfecture de Police Ad'AP list). Scope 'establishment'. |
| capacity_min | number | beta · sur demande (scope establishment) Minimum hall gauge (seats). Scope 'establishment'. |
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/venues?city=Paris&limit=10"
Response
{
"data": [
{
"id": "7b1e2d90-4a6c-4f0e-8c21-5d6e7f8a9b0c",
"supabaseId": null,
"name": "Cinéma Exemple",
"address": "1 rue de l'Exemple",
"city": "Paris",
"latitude": 48.8566,
"longitude": 2.3522,
"venueType": "cinema",
"venueCategories": null,
"website": null,
"metadata": null,
"imageUrl": null,
"imageAttribution": null,
"geofenceRadius": null,
"mentionCount": 0
}
],
"count": 1
}
/api/venues/:id
Get a venue with its event count
Parameters
| include | string | beta · sur demande (scope establishment) establishment → adds `establishment` {kind, accessibility, erp, capacity, sources[]} (beta, key scope 'establishment' on request, else 403). Weak ETag + Cache-Control: private, max-age=3600. Credit each sources[] entry (licence + observedAt) when redistributing. |
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/venues/UUID"
Response
{
"id": "7b1e2d90-4a6c-4f0e-8c21-5d6e7f8a9b0c",
"supabaseId": null,
"name": "Cinéma Exemple",
"address": "1 rue de l'Exemple",
"city": "Paris",
"latitude": 48.8566,
"longitude": 2.3522,
"venueType": "cinema",
"venueCategories": null,
"website": null,
"metadata": null,
"imageUrl": null,
"imageAttribution": null,
"geofenceRadius": null,
"mentionCount": 0,
"source": null,
"sourceId": null,
"isActive": 1,
"createdAt": "2026-09-01T08:00:00.000Z",
"updatedAt": "2026-09-21T08:00:00.000Z",
"eventCount": 42
}
/api/venues/:id/seances
List upcoming seances at a venue
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/venues/UUID/seances"
Response
{ "data": [{ "id": "uuid", "startsAt": "..." }] }
/api/venues/:id/mentions
Critic/social opinions mentioning a venue (restaurant/bar reviews)
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/venues/UUID/mentions"
Response
{ "data": [{ "criticName": "...", "opinionSummary": "..." }] }
/api/venues/trending
"À la mode" venues ranked by recency × authority × sentiment
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/venues/trending"
Response
{ "data": [{ "id": "uuid", "name": "...", "trendingScore": 0.82 }] }
/api/venues/submissions
Submit a user-suggested venue for review
Parameters
| body | json | Request body (JSON) |
Example
curl -X POST -H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "...", "category": "bar", "address": "...", "lat": 48.88, "lng": 2.34, "device_id_hash": "<64 hex>" }' \
"https://celyn.io/api/venues/submissions"
Response
{ "id": "uuid", "status": "pending" }
Seances
/api/seances
List screenings/showtimes
Parameters
| venue_id | string | Filter by venue UUID |
| oeuvre_id | string | Filter by oeuvre UUID |
| lat | number | Latitude for geo search |
| lng | number | Longitude for geo search |
| radius_km | number | Search radius (default: 20) |
| from | string | Start date (ISO 8601) |
| to | string | End date (ISO 8601) |
| limit | number | Max results (default: 50, max: 200) |
| offset | number | Pagination offset |
Example
curl -H "x-api-key: YOUR_KEY" \ "https://celyn.io/api/seances?oeuvre_id=UUID&from=2026-04-01"
Response
{ "data": [{ "id": "uuid",
"startsAt": "2026-04-03T20:30:00Z",
"room": "Salle 1", "price": 9.5,
"oeuvre": { "title": "Anora", "type": "film" },
"venue": { "name": "Le Varietes" } }],
"count": 1 }
/api/seances/:id
Get a single seance by ID
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/seances/UUID"
Response
{ "id": "uuid", "startsAt": "2026-04-03T20:30:00Z",
"oeuvre": { "title": "Anora", ... },
"venue": { "name": "Le Varietes", ... } }
Oeuvres
/api/oeuvres
List curated oeuvres with type/topic filters
Parameters
| oeuvre_type | string | Filter by type: film, play, concert, etc. |
| topic | string | Filter by topic keyword(s) |
| sort | string | "mentioned": most recently discussed first; adds sourceCount, lastMentionedAt, releaseDateTheatricalFr/DigitalFr/TvFr, streamingLatestArrivalAt, nowShowing, nextEpisodeAt (TV rows: next episode air date, YYYY-MM-DD or null), and awards/latestAwardAt on oeuvres with a literary prize selection. Every list shape carries editorialRanks [{list, tier: top10|top25|top50|top100}] on oeuvres present in an editorial best-of list (key absent otherwise). "upcoming": films releasing in FR cinemas within within_days (default 60), playable trailer (trailerUrl) first, then external trailer page (trailerExternalUrl), then soonest; adds the same release/nowShowing fields |
| within_days | number | sort=upcoming window in days (default 60, clamped 1..180) |
| award | string | Only oeuvres with a literary prize selection/win for this prize slug (goncourt, renaudot, femina, medicis, ...) |
| awarded | boolean | "true": only oeuvres with any literary prize selection/win |
| provider | string | FR streaming platform(s): TMDB provider id or slug from /api/oeuvres/providers (netflix, prime-video, crunchyroll, france-tv, ...), comma-separated = any of. Matches offers included with the service (flatrate/free/ads), not rent/buy |
| anime | boolean | "true": only anime (Japanese animation); "false": exclude anime |
| platform | string | Game platform(s) (games only): ps5, ps4, xbox-series, xbox-one, switch, switch-2, pc, mac, ios, android — comma-separated = any of; an unknown slug matches nothing. Game rows carry `platforms`; with sort=upcoming&type=game (games with a Europe/Worldwide release in within_days, soonest first) rows add `upcomingRelease` {date, platforms} |
| limit | number | Max results (default: 50, max: 200) |
| offset | number | Pagination offset |
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/oeuvres?oeuvre_type=film&limit=10"
Response
{
"data": [
{
"id": "b2a4c6e8-1357-4bdf-a024-68ace02468bd",
"title": "Titre d'exemple",
"oeuvreType": "film",
"director": "Nom Réalisateur",
"author": null,
"publisher": null,
"year": 2025,
"imageUrl": null,
"trailerUrl": null,
"trailerExternalUrl": null,
"genres": [
"drame"
],
"description": "Synopsis d'exemple.",
"topics": null,
"curriculumTags": null,
"ageMin": null,
"ageMax": null,
"releaseStatus": null,
"nextAirDate": null,
"lastAirDate": null,
"isAnime": null,
"streamingProviderIds": [],
"createdAt": "2026-09-01T08:00:00.000Z",
"updatedAt": "2026-09-21T08:00:00.000Z"
}
],
"count": 1,
"total": 1,
"syncAt": "2026-09-24T10:00:00.000Z",
"isDelta": false,
"nextCursor": null,
"hasMore": false
}
/api/oeuvres/providers
Beta
FR streaming platforms (Netflix, Prime Video, Crunchyroll, France.tv, ...) with how many oeuvres each includes
Parameters
| min_count | number | Hide platforms with fewer oeuvres (default 1) |
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/oeuvres/providers"
Response
{ "data": [{ "providerId": 8, "slug": "netflix", "name": "Netflix",
"logoUrl": "https://image.tmdb.org/t/p/w92/....jpg",
"oeuvreCount": 812, "tvCount": 640, "filmCount": 172, "animeCount": 41,
"memberProviderIds": [8, 1796] }],
"count": 14, "region": "FR", "attribution": "Where-to-watch data by JustWatch via TMDB" }
/api/oeuvres/game-platforms
Beta
Game platforms (PS5, Xbox Series, Switch, Switch 2, PC, ...) with how many games each has and how many release in the next 180 days
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/oeuvres/game-platforms"
Response
{ "data": [{ "slug": "ps5", "name": "PS5", "gameCount": 412, "upcomingCount": 38 }],
"count": 7, "attribution": "Game data by IGDB.com" }
/api/oeuvres/:id
Get an oeuvre enriched with podcast critic opinions (and literary prize awards, editorial list tiers)
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/oeuvres/UUID"
Response
{ "id": "uuid", "title": "Anora",
"oeuvreType": "film", "director": "Sean Baker",
"year": 2024,
"opinions": [{ "criticName": "Xavier Leherpeur",
"sentiment": "very_positive",
"showName": "Le Masque et la Plume" }],
"opinionCount": 3 }
/api/oeuvres/:id/similar
Find similar oeuvres via vector search
Parameters
| limit | number | Max results (default: 10, max: 50) |
Example
curl -H "x-api-key: YOUR_KEY" \ "https://celyn.io/api/oeuvres/UUID/similar?limit=5"
Response
{ "data": [{ "id": "uuid",
"title": "The Florida Project",
"oeuvreType": "film",
"director": "Sean Baker",
"distance": 0.123 }] }
Podcasts
/api/podcasts/sources
List all tracked podcast shows
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/podcasts/sources"
Response
{ "data": [{ "id": "uuid",
"showName": "Le Masque et la Plume",
"station": "France Inter",
"category": "cinema" }] }
/api/podcasts/episodes
List episodes with oeuvre mention counts
Parameters
| source_id | string | Filter by podcast source UUID |
| limit | number | Max results (default: 20, max: 100) |
Example
curl -H "x-api-key: YOUR_KEY" \ "https://celyn.io/api/podcasts/episodes?limit=5"
Response
{ "data": [{ "id": "uuid",
"title": "Les films de la semaine",
"showName": "Le Masque et la Plume",
"status": "enriched",
"mentionCount": 6 }] }
/api/podcasts/about/:oeuvre_id
Get podcast segments discussing a specific oeuvre
Example
curl -H "x-api-key: YOUR_KEY" \ "https://celyn.io/api/podcasts/about/UUID"
Response
{ "data": [{ "criticName": "Xavier Leherpeur",
"opinionSummary": "A triumph of independent cinema...",
"sentiment": "very_positive",
"showName": "Le Masque et la Plume",
"segmentStart": 340, "segmentEnd": 580 }] }
/api/podcasts/about-source/:source_id
Get podcast segments from a specific source discussing any oeuvre
Example
curl -H "x-api-key: YOUR_KEY" \ "https://celyn.io/api/podcasts/about-source/UUID"
Response
{ "data": [{ "rawTitle": "Anora",
"sentiment": "very_positive",
"opinionSummary": "..." }] }
/api/podcasts/feed
Chronological feed of recent podcast mentions
Parameters
| limit | number | Max results (default: 20, max: 50) |
| source_type | string | Only items from sources of this type: rss (audio podcasts), youtube (videos), instagram, … Unknown value → 400 |
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/podcasts/feed?limit=10"
Response
{ "data": [{ "id": "uuid", "rawTitle": "Anora",
"showName": "Le Masque et la Plume" }] }
/api/podcasts/recommendations
Recommend episodes by semantic similarity to an oeuvre
Parameters
| similar_to | string | Oeuvre UUID (required) |
| limit | number | Max results (default: 10, max: 50) |
Example
curl -H "x-api-key: YOUR_KEY" \ "https://celyn.io/api/podcasts/recommendations?similar_to=UUID&limit=5"
Response
{ "data": [{ "episodeId": "uuid",
"episodeTitle": "Les films de la semaine",
"showName": "Le Masque et la Plume",
"distance": 0.234 }] }
Recommendations
/api/recommendations/:oeuvreId
Multi-dimensional ranked recommendations based on a source oeuvre
Parameters
| lat | number | Latitude for geo proximity scoring |
| lng | number | Longitude for geo proximity scoring |
| radius_km | number | Geo search radius in km (default: 25) |
| from | string | Start date filter (ISO 8601) |
| to | string | End date filter (ISO 8601) |
| category | string | Oeuvre type: film, play, concert, etc. |
| context | string | Usage context (e.g. family outing, date night) |
| grade | string | School grade filter — maternelle: PS, MS, GS; primaire: CP, CE1, CE2, CM1, CM2; collège: 6eme→3eme; lycée: seconde, premiere, terminale |
| limit | number | Max results (default: 10, max: 30) |
Example
curl -H "x-api-key: YOUR_KEY" \ "https://celyn.io/api/recommendations/UUID?lat=48.85&lng=2.35&limit=5"
Response
{
"data": [
{
"oeuvreId": "b2a4c6e8-1357-4bdf-a024-68ace02468bd",
"id": "b2a4c6e8-1357-4bdf-a024-68ace02468bd",
"title": "Titre d'exemple",
"oeuvreType": "film",
"director": "Nom Réalisateur",
"author": null,
"year": 2025,
"imageUrl": null,
"score": 0.82,
"explanation": "très similaire thématiquement, bien noté par les critiques",
"signals": {
"embeddingSimilarity": 0.91,
"curatorWeight": 0.75,
"temporalDecay": 0.6,
"geoProximity": 0.4,
"topicalityBoost": 0.55
},
"opinions": [
{
"criticName": "Nom Critique",
"opinionSummary": "Résumé d'exemple.",
"sentiment": "very_positive",
"showName": "Émission d'exemple",
"publishedAt": "2026-09-18T07:00:00.000Z"
}
],
"nearbyEvents": [
{
"venueId": "7b1e2d90-4a6c-4f0e-8c21-5d6e7f8a9b0c",
"venueName": "Cinéma Exemple",
"startTime": "2026-10-03T20:30:00.000Z",
"endTime": null,
"price": 9.5,
"distance_km": 2.1
}
]
}
],
"meta": {
"sourceOeuvreId": "b2a4c6e8-1357-4bdf-a024-68ace02468bd",
"weights": {
"embeddingSimilarity": 0.4,
"curatorWeight": 0.3,
"temporalDecay": 0.15,
"geoProximity": 0.15,
"topicalityBoost": 0.1
},
"candidateCount": 1,
"cachedAt": "2026-09-24T10:00:00.000Z"
}
}
/api/recommendations
AI-powered recommendations using LLM re-ranking with podcast intelligence
Parameters
| body | json | Request body (JSON) |
Example
curl -X POST -H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "preferences": { "mood": "uplifting",
"genres": ["drama"] }, "limit": 5 }' \
"https://celyn.io/api/recommendations"
Response
{ "data": [{ "id": "uuid", "title": "Anora",
"oeuvreType": "film",
"recommendation_reason": "Highly praised...",
"opinions": [{ "sentiment": "very_positive" }] }],
"reasoning": "Based on your preferences..." }
Batch Recommendations
/api/recommendations/batch
Batch multiple recommendation queries with deduplication
Parameters
| body | json | Request body (JSON) |
Example
curl -X POST -H "x-api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "queries": [{ "topics": ["jazz"],
"location": { "lat": 48.85, "lng": 2.35 },
"limit": 5 }] }' \
"https://celyn.io/api/recommendations/batch"
Response
{ "results": [{ "query_index": 0,
"recommendations": [...] }],
"shared": [] }
Curators
/api/curators
List all podcast sources ranked by curator authority
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/curators"
Response
{ "data": [{ "sourceId": "uuid",
"showName": "Le Masque et la Plume",
"station": "France Inter",
"credibilityScore": 0.95,
"tier": "reference",
"category": "critique",
"isVerified": true,
"mentionCount": 87,
"episodeCount": 31 }] }
/api/curators/:source_id
Get detailed authority info for a specific podcast source
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/curators/UUID"
Response
{ "data": { "sourceId": "uuid",
"showName": "Le Masque et la Plume",
"station": "France Inter",
"credibilityScore": 0.95,
"tier": "reference",
"isVerified": true,
"notes": "Institution de la critique culturelle depuis 1955",
"recentMentions": [{ "rawTitle": "Anora",
"sentiment": "very_positive",
"criticName": "Xavier Leherpeur",
"opinionSummary": "A triumph of independent cinema..." }] } }
Search
/api/search/thematic
Semantic search across oeuvres, events, and podcasts
Parameters
| q | string | Search query (required) |
| type | string | Comma-separated: oeuvre, event, podcast |
| limit | number | Max results (default: 20) |
| age_min | number | Minimum recommended age |
| age_max | number | Maximum recommended age |
| grade | string | School grade filter — maternelle: PS, MS, GS; primaire: CP, CE1, CE2, CM1, CM2; collège: 6eme→3eme; lycée: seconde, premiere, terminale |
Example
curl -H "x-api-key: YOUR_KEY" \ "https://celyn.io/api/search/thematic?q=cinema%20francais&type=oeuvre,event&limit=10"
Response
{ "results": [{ "type": "oeuvre", "id": "uuid",
"title": "Anora", "score": 0.87,
"topics": ["cinema", "independant"] }],
"query": "cinema francais", "total": 1 }
Critics
/api/critics
Beta
List critics with their podcast authority profile
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/critics"
Response
{ "data": [{ "criticName": "Xavier Leherpeur",
"showName": "Le Masque et la Plume",
"mentionCount": 87 }] }
Festivals
/api/festivals
Beta
List upcoming festival editions
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/festivals"
Response
{ "data": [{ "editionId": "uuid",
"title": "We Love Green", "year": 2026 }] }
/api/festivals/:editionId/lineup
Beta
Artist grid for a festival edition (stage/day lineup)
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/festivals/UUID/lineup"
Response
{ "data": [{ "stage": "La Prairie",
"entries": [{ "artistName": "...", "slotStart": "..." }] }] }
/api/festivals/:editionId/events
Beta
Event programme bridged to a festival edition
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/festivals/UUID/events"
Response
{ "data": [{ "id": "uuid", "title": "...", "startTime": "..." }] }
/api/festivals/by-oeuvre/:oeuvreId
Beta
Which festivals feature a given artist/oeuvre
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/festivals/by-oeuvre/UUID"
Response
{ "data": [{ "editionId": "uuid", "title": "We Love Green", "year": 2026 }] }
Albums
/api/albums
Beta
List albums with critic opinions
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/albums"
Response
{ "data": [{ "id": "uuid", "title": "..." }] }
/api/albums/trending
Beta
Trending albums by recent critic mentions
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/albums/trending"
Response
{ "data": [{ "id": "uuid", "title": "..." }] }
/api/albums/featured
Beta
Editorially featured albums
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/albums/featured"
Response
{ "data": [{ "id": "uuid", "title": "..." }] }
/api/albums/:id
Beta
Get a single album with critic opinions
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/albums/UUID"
Response
{ "id": "uuid", "title": "...", "opinions": [] }
/api/albums/:id/similar
Beta
Find similar albums via vector search
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/albums/UUID/similar"
Response
{ "data": [{ "id": "uuid", "title": "...", "distance": 0.1 }] }
Curation
/api/curation/trending
Beta
Trending curated content
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/curation/trending"
Response
{ "data": [] }
/api/curation/feed
Beta
Curated content feed
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/curation/feed"
Response
{ "data": [] }
/api/curation/sources
Beta
Catalogue of curated (featured) sources
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/curation/sources"
Response
{ "data": [] }
/api/curation/sources/:id/feed
Beta
Feed for a single curated source
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/curation/sources/UUID/feed"
Response
{ "data": [] }
/api/curation/sections
Beta
Server-driven curated app sections (ville × type)
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/curation/sections"
Response
{ "data": [] }
/api/curation/sections/:id/content
Beta
Content for a curated section
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/curation/sections/UUID/content"
Response
{ "data": [] }
/api/curation/selection
Beta Accès sur demande
Read this key's curated-source selection
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/curation/selection"
Response
{ "data": [] }
/api/curation/selection/:sourceId
Beta Accès sur demande
Add a source to this key's curated selection
Example
curl -X POST -H "x-api-key: YOUR_KEY" "https://celyn.io/api/curation/selection/UUID"
Response
{ "ok": true }
/api/curation/selection/:sourceId
Beta Accès sur demande
Remove a source from this key's curated selection
Example
curl -X DELETE -H "x-api-key: YOUR_KEY" "https://celyn.io/api/curation/selection/UUID"
Response
{ "ok": true }
Embeddings
/public/embeddings/oeuvres
Beta
Delta-sync feed of oeuvre embedding vectors for on-device ranking (path is /public/embeddings, NOT /api/embeddings: no API key needed)
Parameters
| cursor | string | Opaque pagination cursor from a previous response |
| limit | number | Max results per page |
Example
curl "https://celyn.io/public/embeddings/oeuvres?limit=100"
Response
{ "data": [{ "id": "uuid", "embedding": [0.01, -0.02, ...] }],
"nextCursor": "2026-04-01T00:00:00.000Z:uuid" }
/public/embeddings/curators
Beta
Delta-sync feed of curator (source) taste-vector centroids (path is /public/embeddings, NOT /api/embeddings: no API key needed)
Parameters
| cursor | string | Opaque pagination cursor from a previous response |
| limit | number | Max results per page |
Example
curl "https://celyn.io/public/embeddings/curators?limit=100"
Response
{ "data": [{ "sourceId": "uuid", "embedding": [0.03, 0.11, ...] }],
"nextCursor": "2026-04-01T00:00:00.000Z:uuid" }
Creators
/api/creators/instagram
Beta
Instagram creator signal (venue mentions extracted from IG captions)
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/creators/instagram"
Response
{ "data": [{ "igUsername": "...", "mentionCount": 5 }] }
/api/creators
Beta
List creators (directors, musicians, authors, etc.)
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/creators"
Response
{ "data": [{ "id": "uuid", "name": "Sean Baker" }] }
/api/creators/:id
Beta
Get a single creator with bio and works
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/creators/UUID"
Response
{ "id": "uuid", "name": "Sean Baker", "bio": "..." }
/api/creators/:id/events
Beta
Upcoming events linked to this creator's works
Example
curl -H "x-api-key: YOUR_KEY" "https://celyn.io/api/creators/UUID/events"
Response
{ "data": [] }
Sport (accès sur demande)
/api/sport/feed
Beta Accès sur demande
Football signal feed (transfers, injuries, lineups, quotes)
Parameters
| discipline | string | Discipline slug (football, rugby, cyclisme, athletisme, trail…); default football, `all` for every discipline |
Example
# Access on request — see /portal for contact details. curl -H "x-api-key: YOUR_STATIC_KEY" "https://celyn.io/api/sport/feed"
Response
{ "data": [{ "id": "uuid", "kind": "transfer", "discipline": "football", "rawText": null }], "meta": { "discipline": "football" } }
/api/sport/feed/:id
Beta Accès sur demande
Get a single sport feed item
Example
curl -H "x-api-key: YOUR_STATIC_KEY" "https://celyn.io/api/sport/feed/UUID"
Response
{ "id": "uuid", "kind": "transfer" }
/api/sport/stories
Beta Accès sur demande
Clustered football stories
Parameters
| discipline | string | Discipline slug (football, rugby, cyclisme, athletisme, trail…); default football, `all` for every discipline |
Example
curl -H "x-api-key: YOUR_STATIC_KEY" "https://celyn.io/api/sport/stories"
Response
{ "data": [{ "id": "uuid", "title": "..." }] }
/api/sport/stories/:id
Beta Accès sur demande
Get a single football story
Example
curl -H "x-api-key: YOUR_STATIC_KEY" "https://celyn.io/api/sport/stories/UUID"
Response
{ "id": "uuid", "title": "..." }
/api/sport/entities
Beta Accès sur demande
Canonical football entities (players, clubs, competitions)
Example
curl -H "x-api-key: YOUR_STATIC_KEY" "https://celyn.io/api/sport/entities"
Response
{ "data": [{ "id": "uuid", "name": "..." }] }
/api/sport/results
Beta Accès sur demande
Race results (running/trail/triathlon): race list, or one race's elite/consented results
Example
curl -H "x-api-key: YOUR_STATIC_KEY" "https://celyn.io/api/sport/results?race=trail-de-mios-14km-2026"
Response
{ "data": { "race": { "key": "...", "name": "..." }, "results": [{ "rank": 1, "name": "...", "time": "0:52:46", "publicationBasis": "elite" }] } }
Actu / News (accès sur demande)
/api/news/feed
Beta Accès sur demande
Actu vertical signal feed (reformulated summaries, never raw text)
Example
# Access on request — see /portal for contact details. curl -H "x-api-key: YOUR_STATIC_KEY" "https://celyn.io/api/news/feed"
Response
{ "data": [{ "id": "uuid", "kind": "politique", "summary": "..." }] }
/api/news/feed/:id
Beta Accès sur demande
Get a single news feed item
Example
curl -H "x-api-key: YOUR_STATIC_KEY" "https://celyn.io/api/news/feed/UUID"
Response
{ "id": "uuid", "summary": "..." }
/api/news/stories
Beta Accès sur demande
Clustered news stories
Example
curl -H "x-api-key: YOUR_STATIC_KEY" "https://celyn.io/api/news/stories"
Response
{ "data": [{ "id": "uuid", "title": "..." }] }
/api/news/stories/:id
Beta Accès sur demande
Get a single news story
Example
curl -H "x-api-key: YOUR_STATIC_KEY" "https://celyn.io/api/news/stories/UUID"
Response
{ "data": { "id": "uuid", "title": "...", "events": [], "consensus": { "generatedAt": "2026-09-27T03:40:00.000Z", "eventCount": 82, "independentSourceCount": 12, "facts": [{ "id": "f_1a2b3c4d", "claim": "Le pape Léon XIV célèbre une messe place de la Concorde le 26 septembre.", "facet": "programme", "status": "confirmed", "independentSources": 4, "sources": [{ "name": "Le Monde", "url": "https://..." }], "informativeness": 0.8 }], "contested": [{ "subject": "fidèles place de la Concorde (personne)", "versions": [{ "claim": "...700 000 fidèles...", "sources": [] }, { "claim": "...800 000 fidèles selon le Vatican...", "sources": [] }] }] } } }