POST
/api/uploads/videocolposcopia/{appointment_id}/presignEnvio direto: pedir o endereço
Para arquivos grandes: devolve um endereço temporário para mandar os bytes direto ao armazenamento, sem passar pela API.
- Exige o token de acesso — como obter
- Limite: 60 por minuto, por IP
Headers
| Nome | Tipo | Obrig. | Descrição |
|---|---|---|---|
Authorization | string | Sim | Bearer {access_token}, com o token que o login devolve. |
Content-Type | string | Sim | application/json |
Parâmetros do caminho
| Nome | Tipo | Obrig. | Descrição |
|---|---|---|---|
appointment_id | uuid | Sim | O agendamento. |
Corpo da requisição
| Nome | Tipo | Obrig. | Descrição |
|---|---|---|---|
filename | string | Sim | O nome do arquivo. |
content_type | string | Sim | O tipo (ex.: video/webm, audio/webm). |
size | integer | Não | O tamanho em bytes. Acima de 700 MB a resposta é 413. |
capture_id | string | Não | Um id seu para o arquivo. Pedir de novo com o mesmo id devolve already_uploaded em vez de outro endereço. |
Campos da resposta
| Nome | Tipo | Descrição |
|---|---|---|
upload_url | string | Onde fazer o PUT dos bytes. Vale por 5 minutos. |
public_url | string | O endereço que o arquivo vai ter: é a url do registro em /metadata. |
url | string | O mesmo public_url. |
view_url | string | O link que abre o arquivo, depois que ele subir (vale por até 6 horas). |
filename | string | O nome no armazenamento. |
original_name | string | O nome enviado. |
folder_structure | string | A pasta do exame. |
content_type | string | O tipo. |
already_uploaded | boolean | Só quando o capture_id já tinha subido: vem junto com o public_url, sem upload_url. |
Como enviar um arquivo grande
1
Peça o endereço
Esta rota, com o nome, o tipo e o tamanho do arquivo.
2
Mande os bytes
Um PUT no upload_url, com o mesmo Content-Type pedido.
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/webm" \
--data-binary "@procedimento.webm"3
Registre no exame
POST em /metadata com o public_url e os nomes. Sem este passo, o arquivo fica no armazenamento mas não aparece no exame.
Request URL
https://api-endosystem.imagemais.com.br/api/uploads/videocolposcopia/b4d6f8a0-2c4e-4a6b-8d0f-1a3c5e7b9d2f/presigncurl -X POST "https://api-endosystem.imagemais.com.br/api/uploads/videocolposcopia/b4d6f8a0-2c4e-4a6b-8d0f-1a3c5e7b9d2f/presign" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"filename":"procedimento.webm","content_type":"video/webm","size":157286400}'{
"filename": "procedimento.webm",
"content_type": "video/webm",
...{
"filename": "procedimento.webm",
"content_type": "video/webm",
"size": 157286400
}Respostas
{
"success": true,
"upload_url": "https://<conta>.r2.cloudflarestorage.com/bucket/videocolposcopia/...&X-Amz-Signature=...",
...{
"success": true,
"upload_url": "https://<conta>.r2.cloudflarestorage.com/bucket/videocolposcopia/...&X-Amz-Signature=...",
"key": "videocolposcopia/9d3f1c2a-6b7e-4a8d-9f01-23456789abcd/2026-10-20_09-30-00/c2d4e6f8.webm",
"filename": "c2d4e6f8.webm",
"original_name": "procedimento.webm",
"public_url": "https://storage.exemplo.com/videocolposcopia/9d3f1c2a-6b7e-4a8d-9f01-23456789abcd/2026-10-20_09-30-00/c2d4e6f8.webm",
"folder_structure": "videocolposcopia/9d3f1c2a-6b7e-4a8d-9f01-23456789abcd/2026-10-20_09-30-00",
"content_type": "video/webm",
"capture_type": "capture",
"url": "https://storage.exemplo.com/videocolposcopia/9d3f1c2a-6b7e-4a8d-9f01-23456789abcd/2026-10-20_09-30-00/c2d4e6f8.webm",
"view_url": "https://<conta>.r2.cloudflarestorage.com/<bucket>/videocolposcopia/9d3f1c2a-6b7e-4a8d-9f01-23456789abcd/2026-10-20_09-30-00/c2d4e6f8.webm?X-Amz-Signature=..."
}{
"error": "filename e content_type são obrigatórios"
}{
"error": "filename e content_type são obrigatórios"
}{
"error": "Arquivo excede o limite de 700 MB"
}{
"error": "Arquivo excede o limite de 700 MB"
}{
"error": "Agendamento não encontrado"
}{
"error": "Agendamento não encontrado"
}{
"error": "Muitas requisições. Tente novamente em instantes."
}{
"error": "Muitas requisições. Tente novamente em instantes."
}{
"error": "Token ausente",
"message": "Token de autenticação necessário.",
...{
"error": "Token ausente",
"message": "Token de autenticação necessário.",
"code": "TOKEN_MISSING"
}{
"error": "Token expirado",
"message": "Sua sessão expirou. Faça login novamente.",
...{
"error": "Token expirado",
"message": "Sua sessão expirou. Faça login novamente.",
"code": "TOKEN_EXPIRED"
}{
"error": "Token inválido",
"message": "Token de autenticação inválido. Faça login novamente.",
...{
"error": "Token inválido",
"message": "Token de autenticação inválido. Faça login novamente.",
"code": "TOKEN_INVALID"
}{
"error": "Acesso revogado",
"message": "Seu acesso foi desativado. Procure o administrador da clínica.",
...{
"error": "Acesso revogado",
"message": "Seu acesso foi desativado. Procure o administrador da clínica.",
"code": "ACCESS_REVOKED"
}