Biblioteca
Fotos, videos, PDFs y audios que el equipo y el agente envían, con «cuándo usarlo», temas y consentimiento para fotos de pacientes.
Descarga la proyección completa de la API pública: openapi.json.
Automatizar respuestas y asignaciones explica este recurso en prosa, con ejemplos ejecutables.
| Método | Ruta | Qué hace |
|---|---|---|
GET | /media-assets | List library files |
POST | /media-assets | Upload a file to the library |
DELETE | /media-assets/{id} | Delete a library file |
GET | /media-assets/{id} | Fetch one library file |
PATCH | /media-assets/{id} | Edit a library file |
POST | /media-assets/{id}/file | Replace the file of a library entry |
GET | /media-assets/{id}/url | Get a short-lived URL to a library file |
GET | /media-assets/speakers | List the speakers of the library |
GET /media-assets
List library files
The workspace library, newest first (at most 500; deleted files never appear). Every file carries sendable / unsendable_reason (expired, consent_required — it shows a person whose consent is not confirmed) and a short-lived thumb_url (15 minutes; images and videos). Filters: kind and tag (comma-separated, any), topic_id, q (free text over name, «cuándo usarlo», tags and topic names), ai_enabled, status (live | expired | all, default all).
With conversation_id every file also carries sent_in_conversation, suggested (linked to a topic the conversation’s contact is about) and channel_ok (the conversation’s channel can carry it).
| Parámetro | En | Tipo | Obligatorio | Restricciones |
|---|---|---|---|---|
kind | query | string | no | máx. 500 |
tag | query | string | no | máx. 500 |
topic_id | query | uuid | no | |
q | query | string | no | máx. 200 |
ai_enabled | query | true \ | false | no |
status | query | live \ | expired \ | all |
conversation_id | query | string | no | máx. 64 |
curl https://api.vitrinadev.com/api/v1/media-assets \
-H "Authorization: Bearer $VITRINA_KEY"Ejemplo de respuesta (200)
[
{
"id": "3f6c2b1a-9d4e-4c7b-8a2f-1e0d9c8b7a65",
"kind": "image",
"name": "Plasma — antes/después 1",
"when_to_use": "Cuando pregunten por resultados del plasma",
"caption": "Resultado real tras 3 sesiones",
"tags": [
"antes-despues"
],
"topics": [
{
"id": "8e7d6c5b-4a39-4281-9f0e-d1c2b3a49586",
"name": "Plasma rico en plaquetas",
"kind": "treatment"
}
],
"models": [],
"transcript": null,
"mime_type": "image/jpeg",
"byte_size": 412345,
"duration_ms": null,
"width": 1080,
"height": 1350,
"page_count": null,
"original_filename": "IMG_2231.HEIC",
"ai_enabled": true,
"shows_person": true,
"speaker": null,
"is_intro": false,
"consent_confirmed_at": "2026-10-29T14:00:00.000Z",
"consent_confirmed_by": "2f1e0d9c-8b7a-4c6d-9e5f-1a2b3c4d5e6f",
"expires_at": null,
"expired": false,
"sendable": true,
"unsendable_reason": null,
"send_count": 3,
"last_sent_at": "2026-10-29T15:10:00.000Z",
"thumb_url": "https://storage.example.com/tenants/…/media/3f6c…/l9x2.thumb.webp?X-Amz-Signature=…",
"thumb_expires_at": "2026-10-29T15:25:00.000Z",
"created_by": "2f1e0d9c-8b7a-4c6d-9e5f-1a2b3c4d5e6f",
"created_at": "2026-10-29T13:58:00.000Z",
"updated_at": "2026-10-29T14:00:00.000Z"
}
]Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429
POST /media-assets
Upload a file to the library
Uploads file with its details. The kind (image, video, audio, document) is read from the bytes. Accepted files and caps: images JPG/PNG/WebP/HEIC ≤ 10 MB (auto-rotated, every metadata block — EXIF, GPS — removed, long edge ≤ 2560 px, stored as JPEG, or PNG when it was PNG, ≤ 5 MB); videos MP4/MOV/WebM ≤ 50 MB (converted to a WhatsApp-safe MP4 that must end ≤ 16 MB); PDF ≤ 16 MB; audio OGG/Opus, MP3, M4A/AAC, WAV, WebM, AMR ≤ 16 MB (transcribed unless transcript is sent). Refusals carry details.code: 413 MEDIA_TOO_LARGE (details.limit_bytes), 415 MEDIA_UNSUPPORTED_TYPE (an HEIC the server cannot decode included: convert it to JPG), 422 MEDIA_EMPTY. name defaults to the file name. shows_person defaults to true for images and videos in a healthcare workspace; while it is true and the consent is not confirmed nobody can send the file. A file identical to one already in the library is still created and the answer carries duplicate_of: \{id, name\}. 409 MEDIA_LIBRARY_FULL past 500 files; 422 for an unknown topic. Audio and video may name their speaker («Voz de», ≤ 80 characters; images and PDFs: 400 MEDIA_SPEAKER_KIND). An audio with a speaker may be that speaker’s is_intro («Presentación»): a short greeting the agent is never offered; the platform sends it once per conversation, right before the first audio of that speaker. 400 MEDIA_INTRO_AUDIO_ONLY / MEDIA_INTRO_NEEDS_SPEAKER; one live intro per speaker (case-insensitive): a second is 409 MEDIA_INTRO_EXISTS with details.speaker, details.intro_id, details.intro_name.
Or a JSON body (application/json) — what an MCP connector sends through call_operation, which cannot build multipart: \{ filename, content, content_encoding?, content_type? \} plus the operation's own form fields. content is UTF-8 text by default, or base64 when content_encoding is "base64" (images, PDF, audio, video). The same byte cap applies to the decoded bytes (413 above it); invalid base64 is a 400; the content type defaults from the filename extension.
Cuerpo
| Campo | Tipo | Obligatorio | Restricciones |
|---|---|---|---|
filename | string | sí | mín. 1, máx. 255 |
content | string | sí | mín. 1, máx. 35000000 |
content_encoding | utf8 \ | base64 | — |
content_type | string | — | máx. 200 |
name | string | — | máx. 120 |
when_to_use | string | — | máx. 2000 |
caption | string | — | máx. 1024 |
tags | string[] | — | |
topic_ids | uuid[] | — | |
ai_enabled | boolean | — | |
shows_person | boolean | — | |
consent_confirmed | boolean | — | |
expires_at | string | null | — | date-time |
models | string[] | — | |
transcript | string | — | máx. 8000 |
speaker | string | — | máx. 200 |
is_intro | boolean | — |
curl -X POST https://api.vitrinadev.com/api/v1/media-assets \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"file": "(binary part)",
"name": "Plasma — antes/después 1",
"when_to_use": "Cuando pregunten por resultados del plasma",
"tags": "antes-despues",
"topic_ids": "8e7d6c5b-4a39-4281-9f0e-d1c2b3a49586",
"shows_person": "true",
"consent_confirmed": "true"
}'Ejemplo de respuesta (201)
{
"id": "3f6c2b1a-9d4e-4c7b-8a2f-1e0d9c8b7a65",
"kind": "image",
"name": "Plasma — antes/después 1",
"when_to_use": "Cuando pregunten por resultados del plasma",
"caption": "Resultado real tras 3 sesiones",
"tags": [
"antes-despues"
],
"topics": [
{
"id": "8e7d6c5b-4a39-4281-9f0e-d1c2b3a49586",
"name": "Plasma rico en plaquetas",
"kind": "treatment"
}
],
"models": [],
"transcript": null,
"mime_type": "image/jpeg",
"byte_size": 412345,
"duration_ms": null,
"width": 1080,
"height": 1350,
"page_count": null,
"original_filename": "IMG_2231.HEIC",
"ai_enabled": true,
"shows_person": true,
"speaker": null,
"is_intro": false,
"consent_confirmed_at": "2026-10-29T14:00:00.000Z",
"consent_confirmed_by": "2f1e0d9c-8b7a-4c6d-9e5f-1a2b3c4d5e6f",
"expires_at": null,
"expired": false,
"sendable": true,
"unsendable_reason": null,
"send_count": 3,
"last_sent_at": "2026-10-29T15:10:00.000Z",
"thumb_url": "https://storage.example.com/tenants/…/media/3f6c…/l9x2.thumb.webp?X-Amz-Signature=…",
"thumb_expires_at": "2026-10-29T15:25:00.000Z",
"created_by": "2f1e0d9c-8b7a-4c6d-9e5f-1a2b3c4d5e6f",
"created_at": "2026-10-29T13:58:00.000Z",
"updated_at": "2026-10-29T14:00:00.000Z",
"duplicate_of": null
}Responde: 201 · 400 · 401 · 403 · 404 · 409 · 429
DELETE /media-assets/{id}
Delete a library file
Removes the file from the library and deletes its bytes at once (no undo). Conversations where it was already sent keep their own copy. The send history keeps pointing at it. To stop offering a file without losing it, set expires_at or turn ai_enabled off.
| Parámetro | En | Tipo | Obligatorio | Restricciones |
|---|---|---|---|---|
id | path | uuid | sí |
curl -X DELETE https://api.vitrinadev.com/api/v1/media-assets/<id> \
-H "Authorization: Bearer $VITRINA_KEY"Responde: 204 · 400 · 401 · 403 · 404 · 409 · 429
GET /media-assets/{id}
Fetch one library file
The file with its details, topics, send counters and state. 404 for a deleted file or another workspace’s.
| Parámetro | En | Tipo | Obligatorio | Restricciones |
|---|---|---|---|---|
id | path | uuid | sí |
curl https://api.vitrinadev.com/api/v1/media-assets/<id> \
-H "Authorization: Bearer $VITRINA_KEY"Ejemplo de respuesta (200)
{
"id": "3f6c2b1a-9d4e-4c7b-8a2f-1e0d9c8b7a65",
"kind": "image",
"name": "Plasma — antes/después 1",
"when_to_use": "Cuando pregunten por resultados del plasma",
"caption": "Resultado real tras 3 sesiones",
"tags": [
"antes-despues"
],
"topics": [
{
"id": "8e7d6c5b-4a39-4281-9f0e-d1c2b3a49586",
"name": "Plasma rico en plaquetas",
"kind": "treatment"
}
],
"models": [],
"transcript": null,
"mime_type": "image/jpeg",
"byte_size": 412345,
"duration_ms": null,
"width": 1080,
"height": 1350,
"page_count": null,
"original_filename": "IMG_2231.HEIC",
"ai_enabled": true,
"shows_person": true,
"speaker": null,
"is_intro": false,
"consent_confirmed_at": "2026-10-29T14:00:00.000Z",
"consent_confirmed_by": "2f1e0d9c-8b7a-4c6d-9e5f-1a2b3c4d5e6f",
"expires_at": null,
"expired": false,
"sendable": true,
"unsendable_reason": null,
"send_count": 3,
"last_sent_at": "2026-10-29T15:10:00.000Z",
"thumb_url": "https://storage.example.com/tenants/…/media/3f6c…/l9x2.thumb.webp?X-Amz-Signature=…",
"thumb_expires_at": "2026-10-29T15:25:00.000Z",
"created_by": "2f1e0d9c-8b7a-4c6d-9e5f-1a2b3c4d5e6f",
"created_at": "2026-10-29T13:58:00.000Z",
"updated_at": "2026-10-29T14:00:00.000Z"
}Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429
PATCH /media-assets/{id}
Edit a library file
Changes the details; the bytes are replaced with POST /media-assets/\{id\}/file. tags, topic_ids and models replace their sets. caption: null and expires_at: null clear them. consent_confirmed: true records the calling member and now as the consent confirmation (a member only; an API key gets 422), false clears it. At least one field is required; an unknown topic is 422. speaker: null (or empty) clears the speaker and with it is_intro. Audio and video may name their speaker («Voz de», ≤ 80 characters; images and PDFs: 400 MEDIA_SPEAKER_KIND). An audio with a speaker may be that speaker’s is_intro («Presentación»): a short greeting the agent is never offered; the platform sends it once per conversation, right before the first audio of that speaker. 400 MEDIA_INTRO_AUDIO_ONLY / MEDIA_INTRO_NEEDS_SPEAKER; one live intro per speaker (case-insensitive): a second is 409 MEDIA_INTRO_EXISTS with details.speaker, details.intro_id, details.intro_name.
| Parámetro | En | Tipo | Obligatorio | Restricciones |
|---|---|---|---|---|
id | path | uuid | sí |
Cuerpo
| Campo | Tipo | Obligatorio | Restricciones |
|---|---|---|---|
name | string | — | mín. 1, máx. 120 |
when_to_use | string | — | máx. 2000 |
caption | string | null | — | máx. 1024 |
tags | string[] | — | |
topic_ids | uuid[] | — | |
models | string[] | — | |
transcript | string | null | — | máx. 8000 |
ai_enabled | boolean | — | |
shows_person | boolean | — | |
consent_confirmed | boolean | — | |
expires_at | string | null | — | date-time |
speaker | string | null | — | máx. 200 |
is_intro | boolean | — |
curl -X PATCH https://api.vitrinadev.com/api/v1/media-assets/<id> \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"when_to_use": "Cuando pregunten por resultados del plasma capilar",
"topic_ids": [
"8e7d6c5b-4a39-4281-9f0e-d1c2b3a49586"
],
"consent_confirmed": true
}'Ejemplo de respuesta (200)
{
"id": "3f6c2b1a-9d4e-4c7b-8a2f-1e0d9c8b7a65",
"kind": "image",
"name": "Plasma — antes/después 1",
"when_to_use": "Cuando pregunten por resultados del plasma",
"caption": "Resultado real tras 3 sesiones",
"tags": [
"antes-despues"
],
"topics": [
{
"id": "8e7d6c5b-4a39-4281-9f0e-d1c2b3a49586",
"name": "Plasma rico en plaquetas",
"kind": "treatment"
}
],
"models": [],
"transcript": null,
"mime_type": "image/jpeg",
"byte_size": 412345,
"duration_ms": null,
"width": 1080,
"height": 1350,
"page_count": null,
"original_filename": "IMG_2231.HEIC",
"ai_enabled": true,
"shows_person": true,
"speaker": null,
"is_intro": false,
"consent_confirmed_at": "2026-10-29T14:00:00.000Z",
"consent_confirmed_by": "2f1e0d9c-8b7a-4c6d-9e5f-1a2b3c4d5e6f",
"expires_at": null,
"expired": false,
"sendable": true,
"unsendable_reason": null,
"send_count": 3,
"last_sent_at": "2026-10-29T15:10:00.000Z",
"thumb_url": "https://storage.example.com/tenants/…/media/3f6c…/l9x2.thumb.webp?X-Amz-Signature=…",
"thumb_expires_at": "2026-10-29T15:25:00.000Z",
"created_by": "2f1e0d9c-8b7a-4c6d-9e5f-1a2b3c4d5e6f",
"created_at": "2026-10-29T13:58:00.000Z",
"updated_at": "2026-10-29T14:00:00.000Z"
}Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429
POST /media-assets/{id}/file
Replace the file of a library entry
Swaps the bytes and keeps the entry (id, name, topics, send history). The new file must be the same kind (409 MEDIA_KIND_MISMATCH). Dimensions, duration, page count and (audio) the transcript are re-computed; the consent is CLEARED when the file shows a person (it may be someone else). Accepted files and caps: images JPG/PNG/WebP/HEIC ≤ 10 MB (auto-rotated, every metadata block — EXIF, GPS — removed, long edge ≤ 2560 px, stored as JPEG, or PNG when it was PNG, ≤ 5 MB); videos MP4/MOV/WebM ≤ 50 MB (converted to a WhatsApp-safe MP4 that must end ≤ 16 MB); PDF ≤ 16 MB; audio OGG/Opus, MP3, M4A/AAC, WAV, WebM, AMR ≤ 16 MB (transcribed unless transcript is sent). Refusals carry details.code: 413 MEDIA_TOO_LARGE (details.limit_bytes), 415 MEDIA_UNSUPPORTED_TYPE (an HEIC the server cannot decode included: convert it to JPG), 422 MEDIA_EMPTY.
Or a JSON body (application/json) — what an MCP connector sends through call_operation, which cannot build multipart: \{ filename, content, content_encoding?, content_type? \} plus the operation's own form fields. content is UTF-8 text by default, or base64 when content_encoding is "base64" (images, PDF, audio, video). The same byte cap applies to the decoded bytes (413 above it); invalid base64 is a 400; the content type defaults from the filename extension.
| Parámetro | En | Tipo | Obligatorio | Restricciones |
|---|---|---|---|---|
id | path | uuid | sí |
Cuerpo
| Campo | Tipo | Obligatorio | Restricciones |
|---|---|---|---|
filename | string | sí | mín. 1, máx. 255 |
content | string | sí | mín. 1, máx. 35000000 |
content_encoding | utf8 \ | base64 | — |
content_type | string | — | máx. 200 |
transcript | string | — | máx. 8000 |
curl -X POST https://api.vitrinadev.com/api/v1/media-assets/<id>/file \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{
"file": "(binary part)"
}'Ejemplo de respuesta (200)
{
"id": "3f6c2b1a-9d4e-4c7b-8a2f-1e0d9c8b7a65",
"kind": "image",
"name": "Plasma — antes/después 1",
"when_to_use": "Cuando pregunten por resultados del plasma",
"caption": "Resultado real tras 3 sesiones",
"tags": [
"antes-despues"
],
"topics": [
{
"id": "8e7d6c5b-4a39-4281-9f0e-d1c2b3a49586",
"name": "Plasma rico en plaquetas",
"kind": "treatment"
}
],
"models": [],
"transcript": null,
"mime_type": "image/jpeg",
"byte_size": 412345,
"duration_ms": null,
"width": 1080,
"height": 1350,
"page_count": null,
"original_filename": "IMG_2231.HEIC",
"ai_enabled": true,
"shows_person": true,
"speaker": null,
"is_intro": false,
"consent_confirmed_at": "2026-10-29T14:00:00.000Z",
"consent_confirmed_by": "2f1e0d9c-8b7a-4c6d-9e5f-1a2b3c4d5e6f",
"expires_at": null,
"expired": false,
"sendable": true,
"unsendable_reason": null,
"send_count": 3,
"last_sent_at": "2026-10-29T15:10:00.000Z",
"thumb_url": "https://storage.example.com/tenants/…/media/3f6c…/l9x2.thumb.webp?X-Amz-Signature=…",
"thumb_expires_at": "2026-10-29T15:25:00.000Z",
"created_by": "2f1e0d9c-8b7a-4c6d-9e5f-1a2b3c4d5e6f",
"created_at": "2026-10-29T13:58:00.000Z",
"updated_at": "2026-10-29T14:00:00.000Z"
}Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429
GET /media-assets/{id}/url
Get a short-lived URL to a library file
A signed URL (15 minutes) to view or download the file (variant=original, default) or its thumbnail (variant=thumb; 404 when the file has none — PDFs and audio). disposition=attachment asks the browser to download it. Ask for a new one when it expires; never store it.
| Parámetro | En | Tipo | Obligatorio | Restricciones |
|---|---|---|---|---|
id | path | uuid | sí | |
variant | query | original \ | thumb | no |
disposition | query | inline \ | attachment | no |
curl https://api.vitrinadev.com/api/v1/media-assets/<id>/url \
-H "Authorization: Bearer $VITRINA_KEY"Ejemplo de respuesta (200)
{
"url": "https://storage.example.com/tenants/…/media/3f6c…/l9x2.jpg?X-Amz-Signature=…",
"expires_at": "2026-10-29T15:25:00.000Z",
"mime_type": "image/jpeg"
}Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429
GET /media-assets/speakers
List the speakers of the library
The distinct speaker values («Voz de») of the live files, case-insensitive, by name — the suggestions for a new upload. Each carries how many live files name it and the id of its «Presentación» (intro_id, null when it has none).
curl https://api.vitrinadev.com/api/v1/media-assets/speakers \
-H "Authorization: Bearer $VITRINA_KEY"Ejemplo de respuesta (200)
[
{
"speaker": "Dra. Valentina",
"assets": 4,
"intro_id": "5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d"
}
]Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429