Culture API
Cultural and historical content: topic listings, story detail, OG metadata for deep links, and text-to-speech generation.
Status
Partially available. GET /api/v1/culture/topics, GET /api/v1/culture/stories/:id, and GET /api/v1/culture/stories/:id/meta are implemented under KUB-144, KUB-143, and KUB-140. TTS generation/audio endpoints remain planned under KUB-138.
List Culture Topics
GET /api/v1/culture/topicsReturns all culture topic categories used to group stories.
Response
{
"data": [
{
"id": "21",
"title": "Dominica Heritage",
"slug": "dominica-heritage",
"cover_photo": "http://localhost:8000/storage/101/conversions/dominica-heritage-cover-preview.jpg",
"short_description": "Stories from Dominica's heritage and cultural memory.",
"story_count": 2
},
{
"id": "22",
"title": "Nature & Ecology",
"slug": "nature-ecology",
"cover_photo": "https://cdn.kubuli.com/culture/topics/nature-ecology-cover.jpg",
"short_description": "The Nature Island's ecosystems, species, and landscapes.",
"story_count": 1
}
]
}Responses are cacheable and support ETag / If-None-Match validation for low-churn taxonomy data. Local cover images currently resolve via the admin app storage URL, while remote-reference media returns the upstream CDN URL directly.
Cacheable. Related: KUB-144.
Story Detail
GET /api/v1/culture/stories/:idFull cultural story, including body text and pre-generated TTS audio URL (if available).
Response
{
"data": {
"id": "301",
"title": "The History of the Kalinago People",
"slug": "history-of-the-kalinago-people",
"topic": {
"id": "21",
"name": "Dominica Heritage",
"slug": "dominica-heritage"
},
"body_text": "Explore Dominica's indigenous heritage through the history of the Kalinago people.",
"cover_photo": null,
"tts_audio_url": null,
"reading_time_minutes": 3,
"related_place": null
}
}cover_photo and related_place remain null until story media and place-link data are available in the source schema. tts_audio_url is null until TTS has been generated for the story. Related: KUB-143.
Story OG Metadata
GET /api/v1/culture/stories/:id/metaLightweight OG/social metadata for deep link previews (share sheets, Open Graph tags).
Response
{
"data": {
"title": "The History of the Kalinago People — Kubuli",
"description": "Explore Dominica's indigenous heritage through the history of the Kalinago people.",
"og_image": null,
"canonical_url": "https://kubuli.com/culture/history-of-the-kalinago-people",
"twitter_card": "summary"
}
}description is derived from the current story body text. og_image remains null until story media is available in the source schema, and twitter_card falls back to summary when no share image exists.
Deployments can override the canonical base URL and provide a default share image for stories that do not yet have dedicated media, which upgrades twitter_card to summary_large_image.
Related: KUB-140.
Generate TTS Audio
POST /api/v1/culture/stories/:id/tts
Authorization: Bearer <token>Triggers asynchronous TTS generation for the story. If audio already exists, returns the existing URL immediately.
Response (new job queued)
HTTP/1.1 202 Accepted{
"data": {
"status": "queued",
"message": "TTS generation has been queued.",
"audio_url": null
}
}Response (audio already exists)
HTTP/1.1 200 OK{
"data": {
"status": "ready",
"audio_url": "https://cdn.kubuli.com/tts/story_kalinago.mp3"
}
}Related: KUB-138.
Get TTS Audio
GET /api/v1/culture/stories/:id/audioStreams or redirects to the generated MP3 audio file. Returns 404 if TTS has not yet been generated.
Response
HTTP/1.1 302 Found
Location: https://cdn.kubuli.com/tts/story_kalinago.mp3Or serves the audio directly depending on CDN configuration. Related: KUB-138.