Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/GustavoNightmare/InformacionMuseo/llms.txt

Use this file to discover all available pages before exploring further.

All HTTP endpoints are served by the FastAPI sidecar on port 8010. Public endpoints (/tts/*, /qr/*) require the ?key=<TTS_API_KEY> query parameter. Internal endpoints (/internal/*) require the X-API-Key: <MUSEO_API_KEY> header. Debug endpoints require no authentication.

GET /health

Returns the service status and the configured Edge TTS voice. No authentication required. Use this endpoint for readiness probes in Docker Compose or a load balancer.
curl http://localhost:8010/health
Response 200 OK
{
  "ok": true,
  "service": "museo-tts",
  "voice": "es-CO-GonzaloNeural"
}
ok
boolean
Always true when the service is running.
service
string
Fixed identifier string "museo-tts".
voice
string
Active Edge TTS voice, as set by EDGE_TTS_VOICE (default: es-CO-GonzaloNeural).

POST /internal/species/sync

Pre-generates all three narration-style MP3 files (ficha, narrativo, corto) for a species and registers its QR mapping. Called by the Flask app after every species create or edit operation. Authentication: X-API-Key: <MUSEO_API_KEY> header.
curl -X POST http://localhost:8010/internal/species/sync \
  -H "X-API-Key: YOUR_MUSEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "species_id": "condor-001",
    "qr_id": "qr-condor-001",
    "common_name": "Cóndor Andino",
    "scientific_name": "Vultur gryphus",
    "description": "El cóndor andino es el ave voladora más grande del mundo.",
    "habitat": "los Andes de Sudamérica",
    "diet": "carroña",
    "curiosities": ["Puede planear más de 5 horas sin batir las alas"]
  }'

Request Body — SpeciesSyncRequest

species_id
string
required
Canonical identifier for the species. Must match ^[A-Za-z0-9_-]+$. Used as the audio directory name under AUDIO_CACHE_DIR/species/.
qr_id
string | null
QR code value printed on the physical exhibit label. If null, defaults to species_id internally. Must match ^[A-Za-z0-9_-]+$.
common_name
string | null
Common name of the species (e.g., "Cóndor Andino").
scientific_name
string | null
Scientific/Latin name (e.g., "Vultur gryphus").
description
string | null
Main description text for the species.
habitat
string | null
Natural habitat description.
diet
string | null
Diet or feeding description.
curiosities
any
Interesting facts. Accepts a string, a JSON-encoded string, a list of strings, or a dict of values. All formats are normalised into a list of sentences before TTS synthesis.
Response 200 OK
{
  "ok": true,
  "species_id": "condor-001",
  "qr_id": "qr-condor-001",
  "generated_styles": ["ficha", "narrativo", "corto"],
  "files": {
    "ficha":     "/app/cache_audio/species/condor-001/ficha.mp3",
    "narrativo": "/app/cache_audio/species/condor-001/narrativo.mp3",
    "corto":     "/app/cache_audio/species/condor-001/corto.mp3"
  }
}
ok
boolean
true on success.
species_id
string
Canonical species ID as stored.
qr_id
string
QR ID registered in _qr_index.json.
generated_styles
string[]
List of styles for which MP3 files were generated: ["ficha", "narrativo", "corto"].
files
object
Map of style → absolute file path for each generated MP3.
Errors
StatusDetailCause
400invalid_species_idspecies_id fails regex or is empty
400invalid_qr_idqr_id fails regex
401unauthorizedMissing or wrong X-API-Key header
422empty_tts_text_<style>All species fields empty; nothing to synthesise
500tts_generation_error: …Edge TTS call failed

POST /internal/species/delete

Removes a species’ audio directory and clears all its QR index entries. Called by the Flask app when a species is deleted. Authentication: X-API-Key: <MUSEO_API_KEY> header.
curl -X POST http://localhost:8010/internal/species/delete \
  -H "X-API-Key: YOUR_MUSEO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"species_id": "condor-001", "qr_id": "qr-condor-001"}'

Request Body — SpeciesDeleteRequest

species_id
string
required
Species to delete. Must be non-empty.
qr_id
string | null
Optional explicit QR ID to also remove from the index. If null, only entries pointing to species_id are removed.
Response 200 OK
{
  "ok": true,
  "species_id": "condor-001"
}
Errors
StatusDetailCause
400invalid_species_idspecies_id is blank after sanitisation
401unauthorizedMissing or wrong X-API-Key header

GET /tts/by-qr/

Serves a pre-generated MP3 file for the species associated with the given QR ID. The audio must have been pre-generated by /internal/species/sync beforehand; this endpoint does not synthesise audio on the fly. Authentication: ?key=<TTS_API_KEY> query parameter.
curl -o condor.mp3 \
  "http://localhost:8010/tts/by-qr/qr-condor-001?key=YOUR_TTS_API_KEY&style=narrativo"

Parameters

qr_id
string
required
The QR code value from the exhibit label. Must match ^[A-Za-z0-9_-]+$. Resolved through _qr_index.json to find the species audio directory.
style
string
Narration style to serve. One of ficha, narrativo, corto. Defaults to ficha.
key
string
required
Your TTS_API_KEY.
Response 200 OKaudio/mpeg Binary MP3 stream with the following response headers:
X-TTS-QR
string
The qr_id that was resolved.
X-TTS-Style
string
The narration style that was served (ficha, narrativo, or corto).
X-TTS-Species
string
The resolved species_id whose audio directory was used.
Errors
StatusDetailCause
400invalid_qr_idqr_id path segment fails regex
400invalid_stylestyle is not one of the three allowed values
401unauthorizedMissing or wrong key param
404species_audio_not_foundQR ID not in index and no matching species directory
404pregenerated_audio_not_foundSpecies exists but MP3 for requested style not yet generated

POST /tts/from-text

Synthesises speech from arbitrary text on demand using Edge TTS. The result is returned directly and not cached. Useful for prototyping or generating one-off audio clips. Authentication: ?key=<TTS_API_KEY> query parameter.
curl -X POST "http://localhost:8010/tts/from-text?key=YOUR_TTS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Bienvenidos al Museo BioScan."}' \
  -o output.mp3

Request Body — TextToTTSRequest

text
string
required
Plain text to synthesise. HTML tags are stripped automatically. Must be non-empty after cleaning.
Response 200 OKaudio/mpeg Binary MP3 stream with the following response headers:
X-TTS-Voice
string
Edge TTS voice used for synthesis (from EDGE_TTS_VOICE).
X-TTS-Text-Length
string
Length in characters of the cleaned input text.
Errors
StatusDetailCause
400empty_texttext is blank after HTML-tag stripping
401unauthorizedMissing or wrong key param
500tts_generation_error: …Edge TTS synthesis call failed

POST /qr/resolve-frame

Accepts a raw JPEG image, runs QR detection, and returns the matching species text and audio URL. Use this when you need the species metadata without immediately streaming audio — for example to display species information in a UI before playing sound. Authentication: ?key=<TTS_API_KEY> query parameter. The detection pipeline tries four strategies in sequence, stopping at the first success:
  1. Color — direct detection on the original BGR image
  2. Grayscale — convert to single-channel and retry
  3. Otsu threshold — binarise with Otsu’s method and retry
  4. 2× upscale — resize grayscale image by 2× (cubic interpolation) and retry
curl -X POST "http://localhost:8010/qr/resolve-frame?key=YOUR_TTS_API_KEY&style=ficha" \
  --data-binary "@frame.jpg" \
  -H "Content-Type: image/jpeg"

Parameters

style
string
Narration style for the returned text field. One of ficha, narrativo, corto. Defaults to ficha.
key
string
required
Your TTS_API_KEY.
Request body: Raw JPEG bytes (Content-Type: image/jpeg). Response 200 OK — QR found
{
  "found": true,
  "qr_id": "qr-condor-001",
  "species_id": "condor-001",
  "text": "Este animal llamado Cóndor Andino tiene como nombre científico Vultur gryphus...",
  "audio_url": "http://localhost:8010/tts/by-qr/qr-condor-001?key=YOUR_KEY&style=ficha",
  "fields": {
    "species_id": "condor-001",
    "qr_id": "qr-condor-001",
    "common_name": "Cóndor Andino",
    "scientific_name": "Vultur gryphus",
    "description": "El cóndor andino es el ave voladora más grande del mundo.",
    "habitat": "los Andes de Sudamérica",
    "diet": "carroña",
    "curiosities": ["Puede planear más de 5 horas sin batir las alas"]
  },
  "decode_method": "color",
  "debug_frame_url": "/debug/last-frame"
}
found
boolean
true when a valid QR code was detected and the species was resolved.
qr_id
string
Raw QR code string decoded from the image.
species_id
string
Canonical species ID resolved from the QR index.
text
string
Narration text built from species fields in the requested style.
audio_url
string
Full URL to retrieve the pre-generated MP3 via GET /tts/by-qr/{qr_id}.
fields
object
Cleaned and normalised species fields used to build the narration text.
decode_method
string
Which detection strategy succeeded: color, grayscale, threshold_otsu, or upscaled_gray.
debug_frame_url
string
Path to retrieve the saved debug frame via /debug/last-frame.
Response 404 — QR not found
{
  "found": false,
  "error": "qr_not_found_in_frame",
  "decode_method": "not_found",
  "debug_frame_url": "/debug/last-frame"
}
Errors
StatusDetailCause
400empty_imageRequest body is empty
401unauthorizedMissing or wrong key param
404qr_not_found_in_frameNo QR code detected after all four strategies

POST /tts/from-frame

Combines QR detection and audio delivery into a single request. Accepts a raw JPEG image, detects the QR code, and streams back the pre-generated MP3 for the identified species. Ideal for embedded clients (e.g., ESP32-CAM) that need audio with the fewest round-trips. Authentication: ?key=<TTS_API_KEY> query parameter.
curl -X POST "http://localhost:8010/tts/from-frame?key=YOUR_TTS_API_KEY&style=corto" \
  --data-binary "@frame.jpg" \
  -H "Content-Type: image/jpeg" \
  -o audio.mp3

Parameters

style
string
Narration style for the served MP3. One of ficha, narrativo, corto. Defaults to ficha.
key
string
required
Your TTS_API_KEY.
Request body: Raw JPEG bytes (Content-Type: image/jpeg). Response 200 OKaudio/mpeg Binary MP3 stream. Response headers are identical to GET /tts/by-qr/{qr_id}:
X-TTS-QR
string
Detected QR ID.
X-TTS-Style
string
Narration style served.
X-TTS-Species
string
Resolved species ID.
Errors
StatusDetailCause
400empty_imageRequest body is empty
401unauthorizedMissing or wrong key param
404qr_not_found_in_frameNo QR code detected in image
404pregenerated_audio_not_foundQR resolved but MP3 for style not generated yet

GET /debug/view

Renders a browser-viewable HTML page displaying the last received JPEG frame alongside the current LAST_DEBUG_INFO status JSON. The page auto-refreshes every 3 seconds via <meta http-equiv="refresh">. No authentication required.
# Open in browser
open http://localhost:8010/debug/view

GET /debug/last-frame

Returns the most recently received JPEG frame saved to DEBUG_FRAMES_DIR/last_frame.jpg. No authentication required.
curl http://localhost:8010/debug/last-frame -o last.jpg
Response 200 OKimage/jpeg Raw JPEG bytes of the last processed frame. Errors
StatusDetailCause
404no_debug_frame_yetNo frame has been received since service start

GET /debug/last-status

Returns the in-memory debug state as JSON, reflecting the outcome of the most recent frame processed by /qr/resolve-frame, /tts/from-frame, or the WebSocket stream. No authentication required.
curl http://localhost:8010/debug/last-status
Response 200 OK
{
  "last_qr_text": "qr-condor-001",
  "last_decode_method": "grayscale",
  "last_found": true,
  "last_error": "",
  "last_saved_frame": "/app/debug_frames/incoming_1712345678.jpg",
  "last_timestamp": 1712345678
}
last_qr_text
string
QR code string decoded from the last frame, or "" if none was found.
last_decode_method
string
Detection strategy that last ran: color, grayscale, threshold_otsu, upscaled_gray, or not_found.
last_found
boolean
true if the last frame yielded a valid QR code.
last_error
string
Error string from the last failed detection, e.g., "qr_not_found_in_frame", or "" on success.
last_saved_frame
string
Absolute path to the last debug frame file written to DEBUG_FRAMES_DIR.
last_timestamp
integer
Unix timestamp (seconds) of the last processed frame.

Build docs developers (and LLMs) love