Skip to main content
POST
/
destinos
/
{id}
/
multimedia
curl -X POST https://api.tesisrutas.com/destinos/507f1f77bcf86cd799439011/multimedia \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -F "files=@cathedral_front.jpg" \
  -F "files=@cathedral_interior.jpg" \
  -F "files=@cathedral_tour.mp4"
{
  "message": "Multimedia agregada correctamente",
  "total_actual": 3,
  "archivos": [
    {
      "destino_id": "507f1f77bcf86cd799439011",
      "url": "https://res.cloudinary.com/demo/image/upload/v1234567890/destinations/507f1f77bcf86cd799439011/abc123.jpg",
      "public_id": "destinations/507f1f77bcf86cd799439011/abc123",
      "tipo": "image",
      "formato": "jpg",
      "tamanio_bytes": 2456789,
      "anchura": 1920,
      "altura": 1080,
      "duracion": null,
      "fecha_creacion": "2024-03-05T10:30:00.000Z",
      "activo": true
    },
    {
      "destino_id": "507f1f77bcf86cd799439011",
      "url": "https://res.cloudinary.com/demo/video/upload/v1234567891/destinations/507f1f77bcf86cd799439011/xyz789.mp4",
      "public_id": "destinations/507f1f77bcf86cd799439011/xyz789",
      "tipo": "video",
      "formato": "mp4",
      "tamanio_bytes": 15678912,
      "anchura": 1920,
      "altura": 1080,
      "duracion": 45.3,
      "fecha_creacion": "2024-03-05T10:30:05.000Z",
      "activo": true
    }
  ]
}

Upload Multimedia

Endpoint: POST /destinos/{id}/multimedia Upload images or videos to a destination. Files are stored in Cloudinary with automatic optimization and metadata extraction.
id
string
required
MongoDB ObjectId of the destination

Authentication

Required Role: Admin

Request Body

Content-Type: multipart/form-data
files
file[]
required
Array of files to upload (1-3 files per request)
  • Supports images (jpg, png, gif, etc.)
  • Supports videos (mp4, mov, avi, etc.)
  • Auto-detected by Cloudinary’s resource_type: "auto"

Response

message
string
Success message
total_actual
number
New total count of multimedia files for this destination
archivos
array
Array of uploaded file metadata
archivos[].destino_id
string
ID of the destination
archivos[].url
string
Cloudinary secure URL
archivos[].public_id
string
Cloudinary public ID (used for deletion)
archivos[].tipo
string
Resource type: “image” or “video”
archivos[].formato
string
File format (e.g., “jpg”, “mp4”)
archivos[].tamanio_bytes
number
File size in bytes
archivos[].anchura
number
Width in pixels (for images/videos)
archivos[].altura
number
Height in pixels (for images/videos)
archivos[].duracion
number
Duration in seconds (videos only)
archivos[].fecha_creacion
string
ISO 8601 upload timestamp
archivos[].activo
boolean
Always true
curl -X POST https://api.tesisrutas.com/destinos/507f1f77bcf86cd799439011/multimedia \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -F "files=@cathedral_front.jpg" \
  -F "files=@cathedral_interior.jpg" \
  -F "files=@cathedral_tour.mp4"
{
  "message": "Multimedia agregada correctamente",
  "total_actual": 3,
  "archivos": [
    {
      "destino_id": "507f1f77bcf86cd799439011",
      "url": "https://res.cloudinary.com/demo/image/upload/v1234567890/destinations/507f1f77bcf86cd799439011/abc123.jpg",
      "public_id": "destinations/507f1f77bcf86cd799439011/abc123",
      "tipo": "image",
      "formato": "jpg",
      "tamanio_bytes": 2456789,
      "anchura": 1920,
      "altura": 1080,
      "duracion": null,
      "fecha_creacion": "2024-03-05T10:30:00.000Z",
      "activo": true
    },
    {
      "destino_id": "507f1f77bcf86cd799439011",
      "url": "https://res.cloudinary.com/demo/video/upload/v1234567891/destinations/507f1f77bcf86cd799439011/xyz789.mp4",
      "public_id": "destinations/507f1f77bcf86cd799439011/xyz789",
      "tipo": "video",
      "formato": "mp4",
      "tamanio_bytes": 15678912,
      "anchura": 1920,
      "altura": 1080,
      "duracion": 45.3,
      "fecha_creacion": "2024-03-05T10:30:05.000Z",
      "activo": true
    }
  ]
}

Upload Constraints

Per-Request Limit: 1-3 files per requestGlobal Limit: Maximum 10 files per destinationThe endpoint validates both constraints before uploading.

Examples:

  • Destination has 0 files → Can upload 1-3 files
  • Destination has 8 files → Can upload 1-2 files
  • Destination has 10 files → Cannot upload (returns 400 error)

Delete Multimedia

Endpoint: DELETE /destinos/{id}/multimedia Remove a specific multimedia file from a destination.
id
string
required
MongoDB ObjectId of the destination
public_id
string
required
Cloudinary public_id of the file to delete

Authentication

Required Role: Admin

Response

message
string
Success message
public_id
string
The deleted file’s public_id
error_cloudinary
string
Cloudinary error message (if deletion from cloud failed)
curl -X DELETE "https://api.tesisrutas.com/destinos/507f1f77bcf86cd799439011/multimedia?public_id=destinations/507f1f77bcf86cd799439011/abc123" \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN"
{
  "message": "Multimedia eliminada correctamente",
  "public_id": "destinations/507f1f77bcf86cd799439011/abc123"
}

Implementation Details

Upload Process

  1. Validation
    • Checks 1-3 files per request
    • Verifies destination exists and is active
    • Validates global 10-file limit
    • Calculates remaining capacity
  2. Cloudinary Upload
    • Uploads files asynchronously using asyncio.gather()
    • Uses folder structure: destinations/{destino_id}/
    • Auto-detects resource type (image/video)
    • Extracts metadata (dimensions, format, size, duration)
  3. Database Storage
    • Creates Multimedia entities
    • Stores using AgregarMultimediaDestinoUseCase
    • Uses MongoDB $push with $each operator
    • Appends to multimedia array in destination document
  4. Rollback on Failure
    • If database save fails, deletes uploaded files from Cloudinary
    • Uses cloudinary.uploader.destroy() for each public_id
    • Prevents orphaned files in cloud storage
Source: destinos_router.py:96-201

Delete Process

  1. Validation
    • Verifies destination exists
    • Checks multimedia array is not empty
    • Finds file by public_id
  2. Database Removal
    • Uses EliminarMultimediaDestinoUseCase
    • Removes via MongoDB $pull operator
    • Updates the destination’s multimedia array
  3. Cloudinary Deletion
    • Calls cloudinary.uploader.destroy(public_id, resource_type=tipo)
    • Uses correct resource_type (“image” or “video”)
    • Returns graceful error if cloud deletion fails
Note: If Cloudinary deletion fails, the file is still removed from the database. This prevents broken references but may leave orphaned files in Cloudinary. Source: destinos_router.py:205-254

Cloudinary Configuration

The multimedia endpoints integrate with Cloudinary using:
  • Configuration loaded from src/infrastructure/services/cloudinary_config.py
  • Folder structure: destinations/{destino_id}/
  • Automatic resource type detection
  • Secure HTTPS URLs
  • Async upload for performance
File Limits:
  • Per request: 1-3 files
  • Per destination: 10 files maximum
  • No explicit file size limits (handled by Cloudinary)

Build docs developers (and LLMs) love