Galerias e arquivos (referência)
GET /v1/galleries
Seção intitulada “GET /v1/galleries”Lista as galerias visíveis ao token
Retorna as galerias do time do token (ou apenas as permitidas, se o token for restrito).
Escopo exigido: assets:read.
Escopo exigido: assets:read · operationId: listGalleries
| Parâmetro | Em | Tipo | Obrig. | Descrição |
|---|---|---|---|---|
project |
query | string | não | Filtra por id de projeto. |
cursor |
query | string | não | Cursor opaco devolvido em next_cursor da página anterior. |
Resposta 200
Seção intitulada “Resposta 200”Página de galerias.
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
next_cursor |
string|null | sim | Passe em cursor para a próxima página; null ao fim. |
has_more |
boolean | sim | Há mais páginas. |
items |
array | sim | |
items[].id |
string | sim | |
items[].key |
string | sim | Chave pública imutável usada nas URLs. |
items[].name |
string | sim | |
items[].bucket |
object | sim | |
items[].bucket.id |
string | sim | |
items[].bucket.label |
string | sim | Rótulo do host. |
items[].bucket.kind |
enum(shared, dedicated) | sim | |
items[].bucket.host |
string | sim | |
items[].project |
object | null | sim | |
items[].assets_count |
integer | sim | |
items[].bytes |
integer | sim | |
items[].created_at |
string | sim |
{ "items": [ { "id": "gal_01J9ZK5Q", "key": "marcas-k7p2", "name": "Marcas", "bucket": { "id": "bkt_01J9ZG00", "label": "media", "kind": "shared", "host": "media.nebularcdn.com" }, "project": { "id": "prj_01J9ZK3M", "name": "Site Acme", "slug": "site-acme" }, "assets_count": 12, "bytes": 4823910, "created_at": "2026-10-09T14:03:11Z" } ], "next_cursor": null, "has_more": false}Erros comuns
Seção intitulada “Erros comuns”Corpo {"error", "message", "details"?} (veja Autenticação e visão geral e a tabela de erros): 400 Entrada inválida (nome de arquivo fora das regras, cursor malformado, formulário sem file, nome de galeria vazio ou longo); 401 Token ausente, inválido, expirado ou revogado. A resposta é genérica de propósito; 403 O token não tem o escopo exigido pela operação; 429 Limite de requisições excedido. Espere Retry-After segundos; 503 Serviço (ex.: scanner ou borda) temporariamente indisponível. Tente de novo após Retry-After.
POST /v1/galleries
Seção intitulada “POST /v1/galleries”Cria uma galeria
Cria a galeria no bucket padrão do time. A key pública é gerada pelo servidor e é imutável.
Escopo exigido: galleries:manage. Um token restrito a galerias específicas não pode criar
galerias (a nova ficaria fora da lista dele): recebe 403 forbidden.
Escopo exigido: galleries:manage · operationId: createGallery
Corpo (application/json)
Seção intitulada “Corpo (application/json)”| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
name |
string | sim | |
project_id |
string | não | Projeto ao qual a galeria será associada (organização apenas). |
{ "name": "Marcas", "project_id": "prj_01J9ZK3M"}Resposta 201
Seção intitulada “Resposta 201”Galeria criada.
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
id |
string | sim | |
key |
string | sim | Chave pública imutável usada nas URLs. |
name |
string | sim | |
bucket |
object | sim | |
bucket.id |
string | sim | |
bucket.label |
string | sim | Rótulo do host. |
bucket.kind |
enum(shared, dedicated) | sim | |
bucket.host |
string | sim | |
project |
object | null | sim | |
assets_count |
integer | sim | |
bytes |
integer | sim | |
created_at |
string | sim |
{ "id": "gal_01J9ZK5Q", "key": "marcas-k7p2", "name": "Marcas", "bucket": { "id": "bkt_01J9ZG00", "label": "media", "kind": "shared", "host": "media.nebularcdn.com" }, "project": { "id": "prj_01J9ZK3M", "name": "Site Acme", "slug": "site-acme" }, "assets_count": 0, "bytes": 0, "created_at": "2026-10-09T14:03:11Z"}Erros comuns
Seção intitulada “Erros comuns”Corpo {"error", "message", "details"?} (veja Autenticação e visão geral e a tabela de erros): 400 Entrada inválida (nome de arquivo fora das regras, cursor malformado, formulário sem file, nome de galeria vazio ou longo); 401 Token ausente, inválido, expirado ou revogado. A resposta é genérica de propósito; 403 O token não tem o escopo exigido pela operação; 404 Recurso inexistente ou pertencente a outro time (indistinguíveis de propósito); 429 Limite de requisições excedido. Espere Retry-After segundos; 503 Serviço (ex.: scanner ou borda) temporariamente indisponível. Tente de novo após Retry-After.
GET /v1/galleries/{key}/assets
Seção intitulada “GET /v1/galleries/{key}/assets”Lista os arquivos de uma galeria
Lista arquivos com URLs e status de varredura. Escopo exigido: assets:read.
Escopo exigido: assets:read · operationId: listAssets
| Parâmetro | Em | Tipo | Obrig. | Descrição |
|---|---|---|---|---|
key |
path | string | sim | Chave pública imutável da galeria (ex.: marcas-k7p2). |
prefix |
query | string | não | Retorna apenas nomes que começam com este prefixo. |
cursor |
query | string | não | Cursor opaco devolvido em next_cursor da página anterior. |
Resposta 200
Seção intitulada “Resposta 200”Página de arquivos.
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
next_cursor |
string|null | sim | Passe em cursor para a próxima página; null ao fim. |
has_more |
boolean | sim | Há mais páginas. |
items |
array | sim | |
items[].id |
string | sim | |
items[].name |
string | sim | |
items[].gallery_key |
string | sim | |
items[].current |
object | sim | |
items[].current.id |
string | sim | |
items[].current.hash |
string | sim | SHA-256 hexadecimal do conteúdo. |
items[].current.bytes |
integer | sim | |
items[].current.content_type |
string | sim | Detectado pelo conteúdo. |
items[].current.class |
enum(image, svg, font, media, document, markup, archive, binary) | sim | Classe do arquivo, detectada pelo conteúdo. Define como a CDN serve o arquivo (ver descrição geral). |
items[].current.width |
integer|null | sim | Somente imagens. |
items[].current.height |
integer|null | sim | Somente imagens. |
items[].current.variants |
array |
sim | Larguras de variantes geradas (imagens). |
items[].current.scan |
object | sim | |
items[].current.scan.status |
enum(pending, clean, rejected, quarantined) | sim | pending: aguardando varredura, não publicado. clean: publicado. rejected: recusado. quarantined: detectado na varredura diária; deixou de ser servido (451). |
items[].current.scan.reason |
string|null | sim | Motivo da recusa ou quarentena. |
items[].current.scan.engine |
string|null | sim | |
items[].current.scan.scanned_at |
string|null | sim | |
items[].current.url |
string|null | sim | URL imutável (https://<bucket>.nebularcdn.com/<gallery_key>/<hash[0:12]>/<name>), com Cache-Control: public, max-age=31536000, immutable; null enquanto o arquivo não estiver clean. Para imagens aceita ?w=640 (largura) e ?q= (qualidade); o formato (AVIF/WebP) é negociado por Accept com Vary: Accept. Se a segregação de downloads estiver ligada, classes de download usam outro domínio; use sempre a URL devolvida pela API, sem montá-la. |
items[].current.uploaded_by |
object | sim | |
items[].current.uploaded_by.kind |
enum(user, token) | sim | |
items[].current.uploaded_by.name |
string | sim | |
items[].current.created_at |
string | sim | |
items[].alias_url |
string|null | sim | URL alias (https://<bucket>.nebularcdn.com/<gallery_key>/<name>), sempre a versão atual (max-age=60, stale-while-revalidate=86400); null enquanto não clean. Também aceita ?w=640, ex.: https://media.nebularcdn.com/marcas-k7p2/logos/acme.png?w=640. |
items[].versions_count |
integer | sim | |
items[].created_at |
string | sim |
{ "items": [ { "id": "ast_01J9ZK8W", "name": "logos/acme.png", "gallery_key": "marcas-k7p2", "current": { "id": "ver_01J9ZK8X", "hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "bytes": 48213, "content_type": "image/png", "class": "image", "width": 1200, "height": 630, "variants": [ "320", "640", "1280" ], "scan": { "status": "clean", "reason": null, "engine": "clamav", "scanned_at": "2026-10-09T14:05:02Z" }, "url": "https://media.nebularcdn.com/marcas-k7p2/9f86d081884c/logos/acme.png", "uploaded_by": { "kind": "token", "name": "agente-deploy" }, "created_at": "2026-10-09T14:05:01Z" }, "alias_url": "https://media.nebularcdn.com/marcas-k7p2/logos/acme.png", "versions_count": 1, "created_at": "2026-10-09T14:05:01Z" } ], "next_cursor": null, "has_more": false}Erros comuns
Seção intitulada “Erros comuns”Corpo {"error", "message", "details"?} (veja Autenticação e visão geral e a tabela de erros): 400 Entrada inválida (nome de arquivo fora das regras, cursor malformado, formulário sem file, nome de galeria vazio ou longo); 401 Token ausente, inválido, expirado ou revogado. A resposta é genérica de propósito; 403 O token não tem o escopo exigido pela operação; 404 Recurso inexistente ou pertencente a outro time (indistinguíveis de propósito); 429 Limite de requisições excedido. Espere Retry-After segundos; 503 Serviço (ex.: scanner ou borda) temporariamente indisponível. Tente de novo após Retry-After.
POST /v1/galleries/{key}/assets
Seção intitulada “POST /v1/galleries/{key}/assets”Envia ou versiona um arquivo
Envia um arquivo (multipart). Se o nome já existir, cria uma nova versão; o alias passa a apontar
para ela. Escopo exigido: assets:write.
- 201: varredura concluída e arquivo
clean— já está publicado. - 202: o arquivo está
pending(scanner ocupado ou fora do ar) e não foi publicado. ConsulteGET /v1/galleries/{key}/assets/{name}(campoasset.current.scan.status) periodicamente (comece com 2 s, com backoff) atéscan.statussair depending. Não reenvie o arquivo. - 422: arquivo recusado pela varredura (
malware_detected,svg_unsafe,archive_encrypted,archive_bomb,archive_unsupported). Não tente de novo com o mesmo conteúdo.
Exemplo: curl -H "Authorization: Bearer $NBK" -H "Idempotency-Key: $(uuidgen)" -F file=@logo.png -F name=logos/acme.png https://api.nebularws.com/v1/galleries/marcas-k7p2/assets
Escopo exigido: assets:write · operationId: uploadAsset
| Parâmetro | Em | Tipo | Obrig. | Descrição |
|---|---|---|---|---|
key |
path | string | sim | Chave pública imutável da galeria (ex.: marcas-k7p2). |
Idempotency-Key |
header | string | não | Chave de idempotência (até 255 caracteres; use um UUID). Mesma chave + mesmo corpo ⇒ mesma resposta. Mesma chave + corpo diferente ⇒ 409 idempotency_conflict. |
Corpo (multipart/form-data)
Seção intitulada “Corpo (multipart/form-data)”| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
file |
string | sim | Conteúdo do arquivo (até 25 MB). |
name |
string | não | Nome dentro da galeria: até 4 segmentos separados por /, [a-z0-9._-], até 200 caracteres, sem .., sem segmento iniciando com . e com o primeiro segmento diferente de 12 caracteres hexadecimais. Inválido ⇒ 400 invalid_request. Se omitido, usa o nome do arquivo enviado normalizado. |
Resposta 201
Seção intitulada “Resposta 201”Arquivo publicado (scan.status = clean).
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
id |
string | sim | |
name |
string | sim | |
gallery_key |
string | sim | |
current |
object | sim | |
current.id |
string | sim | |
current.hash |
string | sim | SHA-256 hexadecimal do conteúdo. |
current.bytes |
integer | sim | |
current.content_type |
string | sim | Detectado pelo conteúdo. |
current.class |
enum(image, svg, font, media, document, markup, archive, binary) | sim | Classe do arquivo, detectada pelo conteúdo. Define como a CDN serve o arquivo (ver descrição geral). |
current.width |
integer|null | sim | Somente imagens. |
current.height |
integer|null | sim | Somente imagens. |
current.variants |
array |
sim | Larguras de variantes geradas (imagens). |
current.scan |
object | sim | |
current.scan.status |
enum(pending, clean, rejected, quarantined) | sim | pending: aguardando varredura, não publicado. clean: publicado. rejected: recusado. quarantined: detectado na varredura diária; deixou de ser servido (451). |
current.scan.reason |
string|null | sim | Motivo da recusa ou quarentena. |
current.scan.engine |
string|null | sim | |
current.scan.scanned_at |
string|null | sim | |
current.url |
string|null | sim | URL imutável (https://<bucket>.nebularcdn.com/<gallery_key>/<hash[0:12]>/<name>), com Cache-Control: public, max-age=31536000, immutable; null enquanto o arquivo não estiver clean. Para imagens aceita ?w=640 (largura) e ?q= (qualidade); o formato (AVIF/WebP) é negociado por Accept com Vary: Accept. Se a segregação de downloads estiver ligada, classes de download usam outro domínio; use sempre a URL devolvida pela API, sem montá-la. |
current.uploaded_by |
object | sim | |
current.uploaded_by.kind |
enum(user, token) | sim | |
current.uploaded_by.name |
string | sim | |
current.created_at |
string | sim | |
alias_url |
string|null | sim | URL alias (https://<bucket>.nebularcdn.com/<gallery_key>/<name>), sempre a versão atual (max-age=60, stale-while-revalidate=86400); null enquanto não clean. Também aceita ?w=640, ex.: https://media.nebularcdn.com/marcas-k7p2/logos/acme.png?w=640. |
versions_count |
integer | sim | |
created_at |
string | sim |
{ "id": "ast_01J9ZK8W", "name": "logos/acme.png", "gallery_key": "marcas-k7p2", "current": { "id": "ver_01J9ZK8X", "hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "bytes": 48213, "content_type": "image/png", "class": "image", "width": 1200, "height": 630, "variants": [ "320", "640", "1280" ], "scan": { "status": "clean", "reason": null, "engine": "clamav", "scanned_at": "2026-10-09T14:05:02Z" }, "url": "https://media.nebularcdn.com/marcas-k7p2/9f86d081884c/logos/acme.png", "uploaded_by": { "kind": "token", "name": "agente-deploy" }, "created_at": "2026-10-09T14:05:01Z" }, "alias_url": "https://media.nebularcdn.com/marcas-k7p2/logos/acme.png", "versions_count": 1, "created_at": "2026-10-09T14:05:01Z"}Resposta 202
Seção intitulada “Resposta 202”Aceito, mas ainda não publicado (scan.status = pending). Consulte o GET do arquivo até
scan.status sair de pending. Enquanto pending, content_type/class são provisórios
(application/octet-stream/binary) e width/height são null; os valores reais só aparecem após clean.
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
id |
string | sim | |
name |
string | sim | |
gallery_key |
string | sim | |
current |
object | sim | |
current.id |
string | sim | |
current.hash |
string | sim | SHA-256 hexadecimal do conteúdo. |
current.bytes |
integer | sim | |
current.content_type |
string | sim | Detectado pelo conteúdo. |
current.class |
enum(image, svg, font, media, document, markup, archive, binary) | sim | Classe do arquivo, detectada pelo conteúdo. Define como a CDN serve o arquivo (ver descrição geral). |
current.width |
integer|null | sim | Somente imagens. |
current.height |
integer|null | sim | Somente imagens. |
current.variants |
array |
sim | Larguras de variantes geradas (imagens). |
current.scan |
object | sim | |
current.scan.status |
enum(pending, clean, rejected, quarantined) | sim | pending: aguardando varredura, não publicado. clean: publicado. rejected: recusado. quarantined: detectado na varredura diária; deixou de ser servido (451). |
current.scan.reason |
string|null | sim | Motivo da recusa ou quarentena. |
current.scan.engine |
string|null | sim | |
current.scan.scanned_at |
string|null | sim | |
current.url |
string|null | sim | URL imutável (https://<bucket>.nebularcdn.com/<gallery_key>/<hash[0:12]>/<name>), com Cache-Control: public, max-age=31536000, immutable; null enquanto o arquivo não estiver clean. Para imagens aceita ?w=640 (largura) e ?q= (qualidade); o formato (AVIF/WebP) é negociado por Accept com Vary: Accept. Se a segregação de downloads estiver ligada, classes de download usam outro domínio; use sempre a URL devolvida pela API, sem montá-la. |
current.uploaded_by |
object | sim | |
current.uploaded_by.kind |
enum(user, token) | sim | |
current.uploaded_by.name |
string | sim | |
current.created_at |
string | sim | |
alias_url |
string|null | sim | URL alias (https://<bucket>.nebularcdn.com/<gallery_key>/<name>), sempre a versão atual (max-age=60, stale-while-revalidate=86400); null enquanto não clean. Também aceita ?w=640, ex.: https://media.nebularcdn.com/marcas-k7p2/logos/acme.png?w=640. |
versions_count |
integer | sim | |
created_at |
string | sim |
{ "id": "ast_01J9ZK8W", "name": "logos/acme.png", "gallery_key": "marcas-k7p2", "current": { "id": "ver_01J9ZK8X", "hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "bytes": 48213, "content_type": "application/octet-stream", "class": "binary", "width": null, "height": null, "variants": [], "scan": { "status": "pending", "reason": null, "engine": null, "scanned_at": null }, "url": null, "uploaded_by": { "kind": "token", "name": "agente-deploy" }, "created_at": "2026-10-09T14:05:01Z" }, "alias_url": null, "versions_count": 1, "created_at": "2026-10-09T14:05:01Z"}Resposta 409
Seção intitulada “Resposta 409”Mesma Idempotency-Key usada com um corpo diferente.
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
error |
enum(unauthorized, forbidden, not_found, payload_too_large, quota_exceeded, unsupported_type, class_not_allowed, extension_mismatch, malware_detected, svg_unsafe, archive_encrypted, archive_bomb, archive_unsupported, rate_limited, unavailable, idempotency_conflict, invalid_request, unsupported_media_type, bad_json, too_large, authz_unavailable, database_unavailable, restore_not_removable, gallery_not_empty, bad_body, internal, name_taken, slug_taken, project_quota_exceeded, project_not_empty, deploy_in_progress, nothing_to_rollback, not_cancelable, sensitive_lowered, duplicate_variable, domain_taken, volume_exists, volume_in_use, volume_attached, backup_not_ready, unresolved_reference, reference_cycle, invalid_reference, reference_too_deep, value_too_large) | sim | Código estável para tratamento programático. A tabela completa está na descrição geral. |
message |
string | sim | Mensagem legível em pt-BR. |
details |
object | não | Presente em alguns 422 (ex.: unresolved_reference e reference_cycle trazem details.references). |
details.references |
array |
não | Referências problemáticas (só nomes, nunca valores). |
details.retry_after_seconds |
integer | não | Em 422 rate_limited (ex.: verificação manual de domínio): segundos até poder tentar de novo. |
{ "error": "idempotency_conflict", "message": "Esta Idempotency-Key já foi usada com outro conteúdo. Gere uma chave nova."}Resposta 413
Seção intitulada “Resposta 413”Arquivo acima de 25 MB (ou 40 MP para imagens), ou cota do time excedida
(payload_too_large / quota_exceeded). Reduza o arquivo ou exclua arquivos antigos.
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
error |
enum(unauthorized, forbidden, not_found, payload_too_large, quota_exceeded, unsupported_type, class_not_allowed, extension_mismatch, malware_detected, svg_unsafe, archive_encrypted, archive_bomb, archive_unsupported, rate_limited, unavailable, idempotency_conflict, invalid_request, unsupported_media_type, bad_json, too_large, authz_unavailable, database_unavailable, restore_not_removable, gallery_not_empty, bad_body, internal, name_taken, slug_taken, project_quota_exceeded, project_not_empty, deploy_in_progress, nothing_to_rollback, not_cancelable, sensitive_lowered, duplicate_variable, domain_taken, volume_exists, volume_in_use, volume_attached, backup_not_ready, unresolved_reference, reference_cycle, invalid_reference, reference_too_deep, value_too_large) | sim | Código estável para tratamento programático. A tabela completa está na descrição geral. |
message |
string | sim | Mensagem legível em pt-BR. |
details |
object | não | Presente em alguns 422 (ex.: unresolved_reference e reference_cycle trazem details.references). |
details.references |
array |
não | Referências problemáticas (só nomes, nunca valores). |
details.retry_after_seconds |
integer | não | Em 422 rate_limited (ex.: verificação manual de domínio): segundos até poder tentar de novo. |
{ "error": "payload_too_large", "message": "O arquivo excede o limite de 25 MB."}Resposta 415
Seção intitulada “Resposta 415”Tipo não reconhecido (unsupported_type), classe de arquivo não permitida no bucket
(class_not_allowed) ou extensão divergente do conteúdo detectado (extension_mismatch).
Corrija o nome ou o arquivo.
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
error |
enum(unauthorized, forbidden, not_found, payload_too_large, quota_exceeded, unsupported_type, class_not_allowed, extension_mismatch, malware_detected, svg_unsafe, archive_encrypted, archive_bomb, archive_unsupported, rate_limited, unavailable, idempotency_conflict, invalid_request, unsupported_media_type, bad_json, too_large, authz_unavailable, database_unavailable, restore_not_removable, gallery_not_empty, bad_body, internal, name_taken, slug_taken, project_quota_exceeded, project_not_empty, deploy_in_progress, nothing_to_rollback, not_cancelable, sensitive_lowered, duplicate_variable, domain_taken, volume_exists, volume_in_use, volume_attached, backup_not_ready, unresolved_reference, reference_cycle, invalid_reference, reference_too_deep, value_too_large) | sim | Código estável para tratamento programático. A tabela completa está na descrição geral. |
message |
string | sim | Mensagem legível em pt-BR. |
details |
object | não | Presente em alguns 422 (ex.: unresolved_reference e reference_cycle trazem details.references). |
details.references |
array |
não | Referências problemáticas (só nomes, nunca valores). |
details.retry_after_seconds |
integer | não | Em 422 rate_limited (ex.: verificação manual de domínio): segundos até poder tentar de novo. |
{ "error": "unsupported_type", "message": "Este tipo de arquivo não é permitido neste bucket."}Resposta 422
Seção intitulada “Resposta 422”Recusado pela varredura: malware_detected (a mensagem traz o nome da detecção),
svg_unsafe, archive_encrypted, archive_bomb ou archive_unsupported. A amostra não é guardada. Não reenvie o mesmo conteúdo.
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
error |
enum(unauthorized, forbidden, not_found, payload_too_large, quota_exceeded, unsupported_type, class_not_allowed, extension_mismatch, malware_detected, svg_unsafe, archive_encrypted, archive_bomb, archive_unsupported, rate_limited, unavailable, idempotency_conflict, invalid_request, unsupported_media_type, bad_json, too_large, authz_unavailable, database_unavailable, restore_not_removable, gallery_not_empty, bad_body, internal, name_taken, slug_taken, project_quota_exceeded, project_not_empty, deploy_in_progress, nothing_to_rollback, not_cancelable, sensitive_lowered, duplicate_variable, domain_taken, volume_exists, volume_in_use, volume_attached, backup_not_ready, unresolved_reference, reference_cycle, invalid_reference, reference_too_deep, value_too_large) | sim | Código estável para tratamento programático. A tabela completa está na descrição geral. |
message |
string | sim | Mensagem legível em pt-BR. |
details |
object | não | Presente em alguns 422 (ex.: unresolved_reference e reference_cycle trazem details.references). |
details.references |
array |
não | Referências problemáticas (só nomes, nunca valores). |
details.retry_after_seconds |
integer | não | Em 422 rate_limited (ex.: verificação manual de domínio): segundos até poder tentar de novo. |
{ "error": "malware_detected", "message": "Arquivo recusado: Win.Test.EICAR_HDB-1 detectado."}Erros comuns
Seção intitulada “Erros comuns”Corpo {"error", "message", "details"?} (veja Autenticação e visão geral e a tabela de erros): 400 Entrada inválida (nome de arquivo fora das regras, cursor malformado, formulário sem file, nome de galeria vazio ou longo); 401 Token ausente, inválido, expirado ou revogado. A resposta é genérica de propósito; 403 O token não tem o escopo exigido pela operação; 404 Recurso inexistente ou pertencente a outro time (indistinguíveis de propósito); 429 Limite de requisições excedido. Espere Retry-After segundos; 503 Serviço (ex.: scanner ou borda) temporariamente indisponível. Tente de novo após Retry-After.
GET /v1/galleries/{key}/assets/{name}
Seção intitulada “GET /v1/galleries/{key}/assets/{name}”Detalhe do arquivo, versões, URLs e varredura
Retorna a versão atual, o histórico de versões e o status de varredura. Use para consultar um upload
pending até que scan.status mude. Escopo exigido: assets:read.
Escopo exigido: assets:read · operationId: getAsset
| Parâmetro | Em | Tipo | Obrig. | Descrição |
|---|---|---|---|---|
key |
path | string | sim | Chave pública imutável da galeria (ex.: marcas-k7p2). |
name |
path | string | sim | Nome do arquivo na galeria (até 4 segmentos separados por /, URL-encoded ou não, ex.: logos%2Facme.png). |
Resposta 200
Seção intitulada “Resposta 200”Arquivo.
| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
asset |
object | sim | |
asset.id |
string | sim | |
asset.name |
string | sim | |
asset.gallery_key |
string | sim | |
asset.current |
object | sim | |
asset.current.id |
string | sim | |
asset.current.hash |
string | sim | SHA-256 hexadecimal do conteúdo. |
asset.current.bytes |
integer | sim | |
asset.current.content_type |
string | sim | Detectado pelo conteúdo. |
asset.current.class |
enum(image, svg, font, media, document, markup, archive, binary) | sim | Classe do arquivo, detectada pelo conteúdo. Define como a CDN serve o arquivo (ver descrição geral). |
asset.current.width |
integer|null | sim | Somente imagens. |
asset.current.height |
integer|null | sim | Somente imagens. |
asset.current.variants |
array |
sim | Larguras de variantes geradas (imagens). |
asset.current.scan |
object | sim | |
asset.current.scan.status |
enum(pending, clean, rejected, quarantined) | sim | pending: aguardando varredura, não publicado. clean: publicado. rejected: recusado. quarantined: detectado na varredura diária; deixou de ser servido (451). |
asset.current.scan.reason |
string|null | sim | Motivo da recusa ou quarentena. |
asset.current.scan.engine |
string|null | sim | |
asset.current.scan.scanned_at |
string|null | sim | |
asset.current.url |
string|null | sim | URL imutável (https://<bucket>.nebularcdn.com/<gallery_key>/<hash[0:12]>/<name>), com Cache-Control: public, max-age=31536000, immutable; null enquanto o arquivo não estiver clean. Para imagens aceita ?w=640 (largura) e ?q= (qualidade); o formato (AVIF/WebP) é negociado por Accept com Vary: Accept. Se a segregação de downloads estiver ligada, classes de download usam outro domínio; use sempre a URL devolvida pela API, sem montá-la. |
asset.current.uploaded_by |
object | sim | |
asset.current.uploaded_by.kind |
enum(user, token) | sim | |
asset.current.uploaded_by.name |
string | sim | |
asset.current.created_at |
string | sim | |
asset.alias_url |
string|null | sim | URL alias (https://<bucket>.nebularcdn.com/<gallery_key>/<name>), sempre a versão atual (max-age=60, stale-while-revalidate=86400); null enquanto não clean. Também aceita ?w=640, ex.: https://media.nebularcdn.com/marcas-k7p2/logos/acme.png?w=640. |
asset.versions_count |
integer | sim | |
asset.created_at |
string | sim | |
versions |
array | sim | |
versions[].id |
string | sim | |
versions[].hash |
string | sim | SHA-256 hexadecimal do conteúdo. |
versions[].bytes |
integer | sim | |
versions[].content_type |
string | sim | Detectado pelo conteúdo. |
versions[].class |
enum(image, svg, font, media, document, markup, archive, binary) | sim | Classe do arquivo, detectada pelo conteúdo. Define como a CDN serve o arquivo (ver descrição geral). |
versions[].width |
integer|null | sim | Somente imagens. |
versions[].height |
integer|null | sim | Somente imagens. |
versions[].variants |
array |
sim | Larguras de variantes geradas (imagens). |
versions[].scan |
object | sim | |
versions[].scan.status |
enum(pending, clean, rejected, quarantined) | sim | pending: aguardando varredura, não publicado. clean: publicado. rejected: recusado. quarantined: detectado na varredura diária; deixou de ser servido (451). |
versions[].scan.reason |
string|null | sim | Motivo da recusa ou quarentena. |
versions[].scan.engine |
string|null | sim | |
versions[].scan.scanned_at |
string|null | sim | |
versions[].url |
string|null | sim | URL imutável (https://<bucket>.nebularcdn.com/<gallery_key>/<hash[0:12]>/<name>), com Cache-Control: public, max-age=31536000, immutable; null enquanto o arquivo não estiver clean. Para imagens aceita ?w=640 (largura) e ?q= (qualidade); o formato (AVIF/WebP) é negociado por Accept com Vary: Accept. Se a segregação de downloads estiver ligada, classes de download usam outro domínio; use sempre a URL devolvida pela API, sem montá-la. |
versions[].uploaded_by |
object | sim | |
versions[].uploaded_by.kind |
enum(user, token) | sim | |
versions[].uploaded_by.name |
string | sim | |
versions[].created_at |
string | sim |
{ "asset": { "id": "ast_01J9ZK8W", "name": "logos/acme.png", "gallery_key": "marcas-k7p2", "current": { "id": "ver_01J9ZK8X", "hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "bytes": 48213, "content_type": "image/png", "class": "image", "width": 1200, "height": 630, "variants": [ "320", "640", "1280" ], "scan": { "status": "clean", "reason": null, "engine": "clamav", "scanned_at": "2026-10-09T14:05:02Z" }, "url": "https://media.nebularcdn.com/marcas-k7p2/9f86d081884c/logos/acme.png", "uploaded_by": { "kind": "token", "name": "agente-deploy" }, "created_at": "2026-10-09T14:05:01Z" }, "alias_url": "https://media.nebularcdn.com/marcas-k7p2/logos/acme.png", "versions_count": 1, "created_at": "2026-10-09T14:05:01Z" }, "versions": [ { "id": "ver_01J9ZK8X", "hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "bytes": 48213, "content_type": "image/png", "class": "image", "width": 1200, "height": 630, "variants": [ "320", "640", "1280" ], "scan": { "status": "clean", "reason": null, "engine": "clamav", "scanned_at": "2026-10-09T14:05:02Z" }, "url": "https://media.nebularcdn.com/marcas-k7p2/9f86d081884c/logos/acme.png", "uploaded_by": { "kind": "token", "name": "agente-deploy" }, "created_at": "2026-10-09T14:05:01Z" } ]}Erros comuns
Seção intitulada “Erros comuns”Corpo {"error", "message", "details"?} (veja Autenticação e visão geral e a tabela de erros): 401 Token ausente, inválido, expirado ou revogado. A resposta é genérica de propósito; 403 O token não tem o escopo exigido pela operação; 404 Recurso inexistente ou pertencente a outro time (indistinguíveis de propósito); 429 Limite de requisições excedido. Espere Retry-After segundos; 503 Serviço (ex.: scanner ou borda) temporariamente indisponível. Tente de novo após Retry-After.
DELETE /v1/galleries/{key}/assets/{name}
Seção intitulada “DELETE /v1/galleries/{key}/assets/{name}”Exclui o arquivo
Exclui o arquivo e purga o cache da CDN. O backup retém os bytes por 30 dias. Escopo exigido:
assets:write.
Escopo exigido: assets:write · operationId: deleteAsset
| Parâmetro | Em | Tipo | Obrig. | Descrição |
|---|---|---|---|---|
key |
path | string | sim | Chave pública imutável da galeria (ex.: marcas-k7p2). |
name |
path | string | sim | Nome do arquivo na galeria (até 4 segmentos separados por /, URL-encoded ou não, ex.: logos%2Facme.png). |
Resposta 204
Seção intitulada “Resposta 204”Excluído.
Erros comuns
Seção intitulada “Erros comuns”Corpo {"error", "message", "details"?} (veja Autenticação e visão geral e a tabela de erros): 401 Token ausente, inválido, expirado ou revogado. A resposta é genérica de propósito; 403 O token não tem o escopo exigido pela operação; 404 Recurso inexistente ou pertencente a outro time (indistinguíveis de propósito); 429 Limite de requisições excedido. Espere Retry-After segundos; 503 Serviço (ex.: scanner ou borda) temporariamente indisponível. Tente de novo após Retry-After.