Skip to content

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

http
GET /api/v1/culture/topics

Returns all culture topic categories used to group stories.

Response

json
{
	"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

http
GET /api/v1/culture/stories/:id

Full cultural story, including body text and pre-generated TTS audio URL (if available).

Response

json
{
	"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

http
GET /api/v1/culture/stories/:id/meta

Lightweight OG/social metadata for deep link previews (share sheets, Open Graph tags).

Response

json
{
	"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

http
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
HTTP/1.1 202 Accepted
json
{
	"data": {
		"status": "queued",
		"message": "TTS generation has been queued.",
		"audio_url": null
	}
}

Response (audio already exists)

http
HTTP/1.1 200 OK
json
{
	"data": {
		"status": "ready",
		"audio_url": "https://cdn.kubuli.com/tts/story_kalinago.mp3"
	}
}

Related: KUB-138.


Get TTS Audio

http
GET /api/v1/culture/stories/:id/audio

Streams or redirects to the generated MP3 audio file. Returns 404 if TTS has not yet been generated.

Response

http
HTTP/1.1 302 Found
Location: https://cdn.kubuli.com/tts/story_kalinago.mp3

Or serves the audio directly depending on CDN configuration. Related: KUB-138.

Built with VitePress