JMV Public API
API REST para gerenciamento de vídeos VOD, eventos ao vivo, playlists, streams e upload de arquivos diretamente para o storage S3/MinIO.
Base URLs
Erros
A API usa códigos HTTP padrão. Respostas de erro retornam um objeto com a chave message.
| Código | Significado |
|---|---|
400 | Parâmetros inválidos ou ausentes |
401 | Token ausente, expirado ou inválido |
404 | Recurso não encontrado |
507 | Sem espaço disponível no storage |
500 | Erro interno do servidor |
// Exemplo de resposta de erro
{
"message": "not allowed, token is expired"
}
Autenticação
Gera um token JWT usando apenas o UUID do plano (resource). Endpoint oficial — nenhuma credencial de usuário é necessária.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| resource | string (UUID) | sim | UUID do plano do cliente |
Requisição
POST /v2/authenticate
Content-Type: application/json
{
"resource": "eeba7244-e850-4064-aa61-008718b6e4b0"
}
Resposta — 200 OK
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Usando o token
Inclua o token em todas as requisições autenticadas via header Authorization:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
401 — not allowed, token is expired. Gere um novo token com o endpoint de autenticação.
Payload do JWT (decodificado)
{
"planId": 123,
"planUuid": "eeba7244-e850-4064-aa61-008718b6e4b0",
"planType": "od",
"planDescription": "Plano VOD Enterprise",
"id_customers": 456,
"sub": {
"id_customers": 456,
"email": "admin@empresa.com"
},
"iat": 1750870000,
"exp": 1750884400
}
Vídeos
Todas as rotas de vídeo requerem autenticação via Bearer token.
Retorna a lista paginada de vídeos do plano com opções de filtro e ordenação.
Query Parameters
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
| page | number | 1 | Página atual |
| perPage | number | 10 | Itens por página (máx. 50) |
| sort | ASC | DESC | ASC | Direção da ordenação |
| orderBy | string | name | Campo de ordenação |
| name | string | — | Filtro por nome (like) |
| initialDate | YYYY-MM-DD | — | Data de início do filtro |
| endDate | YYYY-MM-DD | — | Data de fim do filtro |
Retorna um vídeo individual formatado com o secret do plano para geração de URLs assinadas.
Path Parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
| hash | string | Hash único do vídeo (15 chars alfanuméricos) |
Remove um vídeo do plano. A remoção é processada de forma assíncrona — o vídeo fica indisponível imediatamente, mas a exclusão física do arquivo pode levar alguns instantes para ser concluída.
Move um vídeo para uma galeria diferente.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| gallery | string (UUID) | sim | UUID da galeria destino |
Atualiza o nome de exibição de um vídeo.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| name | string | sim | Novo nome do vídeo |
Faz upload de thumbnail via multipart/form-data. Limite de 1 MB. A imagem é enviada para a Static API e o campo thumb do vídeo é atualizado.
multipart/form-data, não application/json.Retorna a lista de vídeos com jobs de conversão em andamento para o plano especificado.
Retorna o status normalizado do job de conversão de um vídeo.
Valores de retorno
| Status | Condição |
|---|---|
COMPLETED | progress ≥ 100 |
CONVERTING | status = converting ou progress > 0 |
ERROR | status = ERROR ou FAILED |
AWAIT_CONVERSION | demais casos |
Galerias
Retorna a árvore de galerias do plano, incluindo galerias filhas (children).
{
"folders": [
{
"id": 1,
"uuid": "a1b2c3d4-...",
"name": "Treinamentos",
"description": "Vídeos de treinamento interno",
"children": []
}
]
}
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| name | string | sim | Nome da galeria |
| description | string | não | Descrição |
| parent | string (UUID) | não | UUID da galeria pai (para criar subgaleria) |
Atualiza nome e/ou descrição de uma galeria existente.
Remove uma galeria. Galerias com vídeos associados não podem ser removidas.
Eventos ao Vivo
Cria um novo evento com status inicial WAITING_LIVE.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| title | string | sim | Título do evento |
| scheduledDate | string (ISO 8601) | sim | Data e hora agendada |
Retorna lista paginada de eventos do plano.
Altera o status de um evento ao vivo. O ciclo de vida segue a sequência:
WAITING_LIVE → LIVE → ON_DEMAND
Remove um ou mais eventos. Aceita array de IDs no body.
Body
{
"ids": [42, 43, 44]
}
Playlist
Gerenciamento de playlists para planos AVJ. Permite ordenar e controlar o conteúdo exibido.
Retorna todos os vídeos da playlist de um plano na ordem configurada.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| videoId | number | sim | ID do vídeo a adicionar |
Altera a posição de um vídeo na playlist.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| position | number | sim | Nova posição (1-based) |
Remove um vídeo da playlist sem excluí-lo do sistema.
Retorna o vídeo atualmente em reprodução no player. Consulta o banco de dados Webtv (leitura em tempo real).
Streams v2
Proxy para o Stream Gateway. Todas as operações são encaminhadas para o serviço interno via X-API-KEY. O stream_id é gerado automaticamente no formato OT-NORMAL-{name}-{stream_key}.
Cria um novo target de stream no Stream Gateway.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| name | string | sim | Nome identificador do stream |
| stream_key | string | sim | Chave única do stream |
Retorna o status atual da transmissão diretamente do Stream Gateway.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| action | enable | disable | sim | Ação a executar na transmissão |
Remove a transmissão do Stream Gateway. Operação irreversível.
Upload S3 v2
Upload de vídeos diretamente para o MinIO (S3-compatible) usando presigned URLs. O conteúdo do arquivo nunca passa pela API — o cliente envia diretamente para o storage. Suporta arquivos de até 5 TB.
POST /v2/upload/multipart/s3 → obter presigned URLs2. PUT para cada URL diretamente no MinIO (client-side) → coletar ETags
3.
POST /v2/upload/multipart/complete → finalizar e processar
Estratégias por tamanho de arquivo
| Tamanho | Estratégia | Chunk Size |
|---|---|---|
| < 100 MB | direct_upload | Arquivo completo (1 parte) |
| 100 MB – 1 GB | medium_chunks | 16 MB |
| 1 GB – 100 GB | large_chunks | 64 MB |
| 100 GB – 5 TB | huge_chunks | Dinâmico (máx. 10.000 partes) |
Cria um multipart upload no MinIO e retorna todas as presigned URLs de uma vez. Cada URL tem validade de 6 horas.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| fileName | string | sim | Nome original do arquivo (com extensão) |
| fileSize | number | sim | Tamanho do arquivo em bytes |
| totalParts | number | sim | Número total de partes a enviar |
| chunkSize | number | sim | Tamanho de cada chunk em bytes |
Requisição
POST /v2/upload/multipart/s3
Authorization: Bearer <token>
Content-Type: application/json
{
"fileName": "video-treinamento.mp4",
"fileSize": 1073741824,
"totalParts": 16,
"chunkSize": 67108864
}
Resposta — 200 OK
{
"uploadId": "minio-upload-id-xyz",
"objectName": "uploads/vod123/a8f3k2m9x1q4p.mp4",
"video_hash": "a8f3k2m9x1q4p",
"totalParts": 16,
"presignedUrls": [
{ "partNumber": 1, "url": "https://minio.../upload?partNumber=1&uploadId=..." },
{ "partNumber": 2, "url": "https://minio.../upload?partNumber=2&uploadId=..." }
]
}
Envio das partes (client-side)
Para cada presigned URL, faça um PUT diretamente no MinIO com o chunk correspondente:
// JavaScript — enviar cada parte
const uploadedParts = [];
for (let i = 0; i < presignedUrls.length; i++) {
const { partNumber, url } = presignedUrls[i];
const start = i * chunkSize;
const chunk = file.slice(start, start + chunkSize);
const res = await fetch(url, {
method: 'PUT',
body: chunk,
headers: { 'Content-Type': 'application/octet-stream' }
});
uploadedParts.push({
partNumber,
etag: res.headers.get('ETag')
});
}
Finaliza o multipart upload no MinIO, registra o vídeo no banco e enfileira o job de processamento na fila s3-upload-queue.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| filename | string | sim | Nome original do arquivo |
| size | number | sim | Tamanho em bytes |
| video_hash | string | sim | Hash retornado pelo init |
| objectName | string | sim | Object name retornado pelo init |
| uploadId | string | sim | Upload ID retornado pelo init |
| parts | array | sim | Array de { partNumber, etag } coletados no envio |
| gallery | string (UUID) | não | UUID da galeria destino |
Requisição
{
"filename": "video-treinamento.mp4",
"size": 1073741824,
"video_hash": "a8f3k2m9x1q4p",
"objectName": "uploads/vod123/a8f3k2m9x1q4p.mp4",
"uploadId": "minio-upload-id-xyz",
"gallery": "a1b2c3d4-e5f6-...",
"parts": [
{ "partNumber": 1, "etag": "\"abc123\"" },
{ "partNumber": 2, "etag": "\"def456\"" }
]
}
Gera uma presigned URL para upload de arquivo em uma única requisição PUT. Validade de 24 horas. Recomendado para arquivos menores que 100 MB.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| filename | string | sim | Nome do arquivo com extensão |
| fileSize | number | sim | Tamanho em bytes |
| gallery | string (UUID) | não | UUID da galeria destino |
Confirma que o arquivo foi enviado para o MinIO via PUT, valida a existência do objeto (headObject), registra o vídeo e enfileira o job de processamento.
Body
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| hash | string | sim | Hash retornado pelo endpoint de criação |
| gallery | string (UUID) | não | UUID da galeria destino |