# Volumes (referência)

## GET `/v1/projects/{p}/services/{s}/volume`

Consulta o volume

`404` quando o serviço não tem volume.

Escopo exigido: `projects:read`.

Escopo exigido: `projects:read` · operationId: `getVolume`

| Parâmetro | Em | Tipo | Obrig. | Descrição |
|---|---|---|---|---|
| `p` | path | string | sim | Id (26 caracteres) ou slug do projeto. Projeto de outro time ou fora dos `project_ids` do token ⇒ `404`. |
| `s` | path | string | sim | Id ou nome do serviço dentro do projeto. |

### Resposta 200

Volume.

| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| `id` | string | sim |  |
| `service_id` | string | sim |  |
| `mount_path` | string | sim |  |
| `size_gb` | integer | sim |  |
| `state` | string | sim | Ciclo do volume (`staged`, `active`, `retired`, `orphaned`). |
| `created_at` | string | sim |  |

```json
{
  "id": "01jb7ka15q8r7t2v4w6x8y0a8i",
  "service_id": "01jb7k4a5q8r7t2v4w6x8y0a2c",
  "mount_path": "/data",
  "size_gb": 5,
  "state": "active",
  "created_at": "2026-10-10T14:03:11Z"
}
```

### Erros comuns

Corpo `{"error", "message", "details"?}` (veja [Autenticação e visão geral](/referencia/autenticacao/) e a [tabela de erros](/erros/tabela/)): `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; `500` Falha interna (`internal`). O detalhe fica só no log do servidor; repita depois, e informe o `Idempotency-Key` ao suporte se persistir; `503` Serviço (ex.: scanner ou borda) temporariamente indisponível. Tente de novo após `Retry-After`.

## PUT `/v1/projects/{p}/services/{s}/volume`

Anexa ou aumenta o volume

Cada serviço tem no máximo um volume persistente (1 a 50 GB). Se já existe, só pode **crescer**.

Escopo exigido: `volumes:write`.

Escopo exigido: `volumes:write` · operationId: `putVolume`

| Parâmetro | Em | Tipo | Obrig. | Descrição |
|---|---|---|---|---|
| `p` | path | string | sim | Id (26 caracteres) ou slug do projeto. Projeto de outro time ou fora dos `project_ids` do token ⇒ `404`. |
| `s` | path | string | sim | Id ou nome do serviço dentro do projeto. |

### Corpo (application/json)

| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| `mount_path` | string | sim | Caminho absoluto dentro do container. Subpastas de /app (ex.: /app/data) são aceitas e ficam graváveis; /app inteiro, /app/.next, /app/.next/cache, /tmp, /proc, /sys, /dev e /etc são recusados. |
| `size_gb` | integer | sim |  |

### Resposta 200

Volume.

| Campo | Tipo | Obrig. | Descrição |
|---|---|---|---|
| `id` | string | sim |  |
| `service_id` | string | sim |  |
| `mount_path` | string | sim |  |
| `size_gb` | integer | sim |  |
| `state` | string | sim | Ciclo do volume (`staged`, `active`, `retired`, `orphaned`). |
| `created_at` | string | sim |  |

```json
{
  "id": "01jb7ka15q8r7t2v4w6x8y0a8i",
  "service_id": "01jb7k4a5q8r7t2v4w6x8y0a2c",
  "mount_path": "/data",
  "size_gb": 5,
  "state": "active",
  "created_at": "2026-10-10T14:03:11Z"
}
```

### Resposta 409

`volume_exists` ou `volume_in_use` (pare o serviço primeiro).

| 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<string> | 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. |

### Resposta 422

`quota_exceeded` (cota de volumes do time ou sem capacidade).

| 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<string> | 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. |

```json
{
  "error": "quota_exceeded",
  "message": "Limite de serviços do plano atingido."
}
```

### Erros comuns

Corpo `{"error", "message", "details"?}` (veja [Autenticação e visão geral](/referencia/autenticacao/) e a [tabela de erros](/erros/tabela/)): `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); `413` Corpo JSON acima do limite da rota (`too_large`); `415` O corpo precisa ser `application/json` (`unsupported_media_type`); `429` Limite de requisições excedido. Espere `Retry-After` segundos; `500` Falha interna (`internal`). O detalhe fica só no log do servidor; repita depois, e informe o `Idempotency-Key` ao suporte se persistir; `503` Serviço (ex.: scanner ou borda) temporariamente indisponível. Tente de novo após `Retry-After`.

## DELETE `/v1/projects/{p}/services/{s}/volume`

Apaga o volume e seus dados

**Irreversível**: apaga os dados do volume. Idempotente (sem volume ⇒ `204`). No painel exige confirmação de identidade (step-up); com token, o escopo `volumes:write` é a autorização.

Escopo exigido: `volumes:write`.

Escopo exigido: `volumes:write` · operationId: `deleteVolume`

| Parâmetro | Em | Tipo | Obrig. | Descrição |
|---|---|---|---|---|
| `p` | path | string | sim | Id (26 caracteres) ou slug do projeto. Projeto de outro time ou fora dos `project_ids` do token ⇒ `404`. |
| `s` | path | string | sim | Id ou nome do serviço dentro do projeto. |

### Resposta 204

Removido (ou já removido anteriormente: repetir é `204`).

### Erros comuns

Corpo `{"error", "message", "details"?}` (veja [Autenticação e visão geral](/referencia/autenticacao/) e a [tabela de erros](/erros/tabela/)): `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; `500` Falha interna (`internal`). O detalhe fica só no log do servidor; repita depois, e informe o `Idempotency-Key` ao suporte se persistir; `503` Serviço (ex.: scanner ou borda) temporariamente indisponível. Tente de novo após `Retry-After`.
