Enviar mídia: arquivo inteiro e partes
Todo vídeo, toda capa e toda foto passam por /v1/media antes de entrar em um post. Há dois caminhos, conforme o tamanho.
| Arquivo inteiro | Em partes | |
|---|---|---|
| Quando | Até 50 MiB | Qualquer tamanho (vídeo até 5 GiB) |
| Como criar | POST /v1/media com simple: true |
POST /v1/media sem simple |
| Como enviar | PUT /v1/media/:id/content com os bytes |
PUT /v1/media/:id/parts/:part para cada parte |
| Como terminar | O próprio PUT conclui |
POST /v1/media/:id/complete |
Tipos e tamanhos aceitos
| Tipo (`type`) | `mime` aceito | Tamanho máximo |
|---|---|---|
video |
video/mp4, video/quicktime |
5 GiB |
cover |
image/png, image/jpeg |
20 MiB |
image |
image/jpeg (só JPEG) |
20 MiB |
image é a foto de um post de imagem. O servidor confere que o arquivo é um JPEG de verdade (422 invalid_image se não for: no envio inteiro, antes de gravar; no envio em partes, ao completar) e lê a largura e a altura do cabeçalho (width e height na mídia). Ele não converte: exporte a foto em JPEG sRGB (o Praeko Studio faz isso).
Foto única no Instagram
Suba a foto com type: image e crie o post com kind: image e uma imagem em media.images (várias seriam um carrossel, que ainda não existe: 422 carousel_not_supported). Só o Instagram aceita foto por enquanto, pelo Buffer ou direto pela Meta; YouTube e TikTok respondem 422 kind_not_supported_by_network.
{
"kind": "image",
"title": "Dica: PRs pequenos",
"media": {
"images": [
{
"media": "01KA3V9...",
"alt": "Slide com o título da dica"
}
]
},
"texts": {
"instagram": {
"text": "Um PR, uma ideia. #devbrasil"
}
},
"items": [
{
"network": "instagram",
"via": "meta",
"queue": true
}
]
}| Regra do Instagram | Valor | Se não cumprir |
|---|---|---|
| Formato | JPEG | 422 invalid_image |
| Tamanho | 8 MB | 422 image_too_large |
| Proporção | de 4:5 a 1,91:1 (use 1080x1350) | 422 image_aspect_ratio |
| Largura | 320 a 1440 px (a Meta amplia ou reduz o resto) | aviso image_small ou image_will_be_resized |
| Legenda | até 2200 caracteres e 30 hashtags | 422 invalid_field |
Texto alternativo (alt) |
até 1000 caracteres | pelo Buffer é ignorado: aviso alt_ignored |
Os avisos voltam em items[].warnings (cada um com code e message, estáveis) e não impedem a criação. Pela Meta, o alt vai no contêiner da foto; pelo Buffer, que não tem texto alternativo documentado, ele é ignorado e o item avisa. O post volta com kind e media.images; a imagem de um post de imagem não troca por PATCH (cancele e crie de novo).
Arquivo inteiro
curl -X POST https://praeko.app/v1/media \
-H "Authorization: Bearer $PRAEKO_KEY" -H "X-Praeko-Contract: en" \
-H "Content-Type: application/json" \
-d '{ "type": "video", "name": "v.mp4", "mime": "video/mp4", "size": 8123456, "simple": true }'
curl -X PUT https://praeko.app/v1/media/$MEDIA_ID/content \
-H "Authorization: Bearer $PRAEKO_KEY" -H "Content-Type: video/mp4" \
--data-binary @v.mp4Com simple: true e size acima de 50 MiB a criação é recusada (422 file_too_large): use partes. O corpo do PUT precisa ter exatamente o size combinado (422 size_mismatch).
Envio em partes
A resposta de POST /v1/media (sem simple) traz minPartSize (5 MiB), maxPartSize (95 MiB) e suggestedPartSize (16 MiB). Numere as partes de 1 a 10000, envie cada uma em PUT /v1/media/:id/parts/:part com os bytes crus e termine com POST /v1/media/:id/complete.
- Todas as partes têm o mesmo tamanho; só a última pode ser menor (
422 parts_unequal). Toda parte, menos a última, precisa ter pelo menos 5 MiB (422 part_too_small); nenhuma passa de 95 MiB (413 part_too_large). - Reenviar a mesma parte é seguro: ela é sobrescrita.
- Se faltar alguma parte da sequência,
completeresponde422 parts_missing; se o total não bate com osizecombinado,422 size_mismatch. - Um envio que não termina em 24 horas é descartado (a mídia sai da biblioteca).
# 16 MiB por parte; a última leva o que sobrar
split -b 16m v.mp4 parte_
n=1; for f in parte_*; do
curl -X PUT "https://praeko.app/v1/media/$MEDIA_ID/parts/$n" \
-H "Authorization: Bearer $PRAEKO_KEY" -H "Content-Type: video/mp4" \
--data-binary @"$f"
n=$((n+1))
done
curl -X POST https://praeko.app/v1/media/$MEDIA_ID/complete \
-H "Authorization: Bearer $PRAEKO_KEY" -H "X-Praeko-Contract: en"Estado e uso
A mídia nasce uploading e vira ready quando o envio termina. Vídeos ready trazem durationMs, width e height quando o cabeçalho do arquivo informa (vídeos antigos ganham os valores na primeira leitura), e GET /v1/media/:id traz também publicUrl. Só use no post uma mídia ready (senão, 409 media_not_ready). DELETE /v1/media/:id recusa mídia usada por um post pendente (409 media_in_use).
durationMs é a duração em milissegundos lida do arquivo. Não confunda com o duration de GET /v1/youtube/videos, que é a duração que o YouTube informa, em ISO 8601 (por exemplo, PT58S).
uploadFile do @praeko/sdk/node envia o arquivo do disco e escolhe o caminho sozinho (um PUT até 32 MiB; acima, partes de 16 MiB): SDK. Um agente com shell usa as ferramentas create_media_upload e complete_media_upload do servidor MCP.