> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cubehosting.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Pedir o envio de um arquivo

> Reserve o envio e receba um link de 15 minutos para mandar o arquivo direto ao armazenamento.

O envio tem três passos:

<Steps>
  <Step title="Peça o envio">
    Mande o nome (`path`), o tamanho exato em bytes (`sizeBytes`) e o tipo (`contentType`). A Cube confere a cota do plano e devolve o link em `upload.url`.
  </Step>

  <Step title="Mande o arquivo no link">
    `PUT` no `upload.url` com o `Content-Type` de `upload.headers` e o arquivo no corpo. O link só aceita esse tamanho e esse tipo, e o arquivo não passa pelo servidor dos projetos.
  </Step>

  <Step title="Confirme">
    Chame [Confirmar o envio](/api-reference/blob/complete). Só então o arquivo aparece na lista.
  </Step>
</Steps>

<Warning>
  Não mande a chave de API no `PUT`: o link já traz a autorização, e ele é só para esse arquivo.
</Warning>

<Note>
  O Blob é dos planos pagos (Block 5 GB, Stack 10 GB, Tower 25 GB, Fortress 50 GB, Monolith 100 GB), com até 4 GB por arquivo. Um envio que você desistir de fazer se cancela com [Apagar](/api-reference/blob/delete); o tamanho dele segue reservado até o link de envio vencer (15 minutos). O arquivo que chega pelo link e não é confirmado em 10 minutos é removido.
</Note>

## Erros comuns

| Código                                                                 | HTTP | O que fazer                                                                              |
| ---------------------------------------------------------------------- | ---- | ---------------------------------------------------------------------------------------- |
| [`invalid_path`](/errors#param-invalid-path)                           | 400  | Use um nome como `img/logo.png`: pastas por `/`, sem `..` e sem `/` no começo ou no fim. |
| [`blob_not_in_plan`](/errors#param-blob-not-in-plan)                   | 403  | Assine um plano pago: o Free não tem Blob.                                               |
| [`insufficient_permission`](/errors#param-insufficient-permission)     | 403  | Use uma chave de leitura e escrita ou Só Blob.                                           |
| [`blob_quota_exceeded`](/errors#param-blob-quota-exceeded)             | 413  | Apague arquivos que não usa ou mude para um plano maior.                                 |
| [`file_too_large`](/errors#param-file-too-large)                       | 413  | Divida o arquivo: cada um tem até 4 GB.                                                  |
| [`blob_object_limit_reached`](/errors#param-blob-object-limit-reached) | 409  | Apague arquivos ou junte os pequenos num `.zip`.                                         |
| [`account_suspended`](/errors#param-account-suspended)                 | 409  | Pague a renovação em Plano e cobrança.                                                   |
| [`blob_unavailable`](/errors#param-blob-unavailable)                   | 503  | Tente de novo em instantes.                                                              |

Todos os códigos, com o formato do erro, em [Códigos de erro](/errors).


## OpenAPI

````yaml POST /blob/objects
openapi: 3.1.0
info:
  title: API da Cube Hosting
  version: 1.0.0
  description: >-
    Hospede bots de Discord, sites e APIs em Node.js e Python: envie o .zip,
    inicie, pare, reinicie, leia logs e métricas, cuide das variáveis de
    ambiente, faça e baixe backups, volte para uma versão anterior, crie bancos
    de dados (PostgreSQL, MySQL, MongoDB e Redis), guarde arquivos privados no
    Blob, use um domínio seu nos sites e veja o uso do plano. Para agentes de
    IA, o servidor MCP da conta (`POST https://app.cubehosting.com.br/api/mcp`,
    JSON-RPC, com a mesma chave) está em
    https://docs.cubehosting.com.br/account-mcp.
  contact:
    name: Cube Hosting
    url: https://discord.gg/pv6D9tUsDV
servers:
  - url: https://app.cubehosting.com.br/api
security:
  - bearerAuth: []
tags:
  - name: Projetos
  - name: Controle
  - name: Logs e métricas
  - name: Variáveis de ambiente
  - name: Backups
  - name: Versões dos envios
  - name: Bancos de dados
  - name: Blob
  - name: Domínios
  - name: Avisos
  - name: Conta
paths:
  /blob/objects:
    post:
      tags:
        - Blob
      summary: Pedir o envio de um arquivo
      description: >-
        Primeiro passo do envio: diga o nome (`path`, com pastas por `/`), o
        tamanho exato em bytes e o tipo, e a resposta traz um link de **15
        minutos** para mandar o arquivo direto ao armazenamento com `PUT`, sem
        passar pelo servidor dos projetos. O link só aceita **esse tamanho e
        esse tipo**: mande o `Content-Type` de `upload.headers` e o corpo com o
        arquivo (o `Content-Length` sai sozinho). **Não mande a chave de API no
        `PUT`**. Depois, chame [Confirmar o
        envio](/api-reference/blob/complete). A cota do plano é conferida aqui
        (somando os envios pedidos nos últimos 15 minutos, com o link ainda
        valendo, mesmo os cancelados) e de novo na confirmação. Um arquivo que
        chega pelo link e não é confirmado em 10 minutos é removido. Mesmo nome
        de um arquivo que já existe: o novo entra no lugar quando for
        confirmado. Cada arquivo tem até 4 GB; o Free não tem Blob.
      operationId: createBlobUpload
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BlobUploadInput'
            example:
              path: img/logo.png
              sizeBytes: 23456
              contentType: image/png
      responses:
        '201':
          description: 'O envio foi reservado: mande o arquivo no link e confirme.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BlobUpload'
              example:
                object:
                  id: 01JA3F7K2M9P4R6T8V0X1Z3B5D
                  path: img/logo.png
                  sizeBytes: 23456
                  contentType: image/png
                  status: pending
                  createdAt: '2026-09-28T13:10:02.000Z'
                upload:
                  url: >-
                    https://…/accounts/…/blob/01JA3F7K2M9P4R6T8V0X1Z3B5D?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=900&X-Amz-SignedHeaders=content-length%3Bcontent-type%3Bhost&X-Amz-Signature=…
                  method: PUT
                  headers:
                    content-type: image/png
                  expiresAt: '2026-09-28T13:25:02.000Z'
        '400':
          description: O corpo, o nome ou o tipo não valem.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                invalid_request:
                  summary: invalid_request
                  value:
                    status: error
                    code: invalid_request
                    message: >-
                      Mande path, sizeBytes (inteiro, em bytes) e, se quiser,
                      contentType.
                invalid_path:
                  summary: invalid_path
                  value:
                    status: error
                    code: invalid_path
                    message: >-
                      Nome de arquivo inválido. Use até 1024 bytes, pastas
                      separadas por "/", sem começar ou terminar com "/" e sem
                      "..".
        '401':
          description: Chave ausente, inválida ou revogada.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                invalid_api_key:
                  summary: invalid_api_key
                  value:
                    status: error
                    code: invalid_api_key
                    message: >-
                      Chave de API inválida ou revogada. Confira o cabeçalho
                      "Authorization: Bearer <chave>" ou crie outra em Chaves de
                      API no painel.
        '403':
          description: A chave é só de leitura, ou o plano não tem Blob (Free).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                insufficient_permission:
                  summary: insufficient_permission
                  value:
                    status: error
                    code: insufficient_permission
                    message: >-
                      Esta chave é só de leitura. Para enviar, iniciar, parar,
                      reiniciar, mexer nas variáveis, fazer e baixar backups,
                      baixar e voltar versões dos envios, criar, ligar, desligar
                      e ver a senha dos bancos de dados ou enviar e apagar
                      arquivos do Blob, crie uma chave de leitura e escrita no
                      painel.
                blob_not_in_plan:
                  summary: blob_not_in_plan
                  value:
                    status: error
                    code: blob_not_in_plan
                    message: >-
                      O Blob é dos planos pagos. Assine um plano em Plano e
                      cobrança para enviar arquivos.
        '409':
          description: A conta chegou a 100.000 arquivos, ou está suspensa.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                blob_object_limit_reached:
                  summary: blob_object_limit_reached
                  value:
                    status: error
                    code: blob_object_limit_reached
                    message: >-
                      O Blob da conta chegou a 100.000 arquivos. Apague os que
                      não usa ou junte arquivos pequenos num .zip.
                account_suspended:
                  summary: account_suspended
                  value:
                    status: error
                    code: account_suspended
                    message: >-
                      Sua conta está suspensa porque o Pix da renovação não foi
                      pago, então os projetos ficam parados. Pague em Plano e
                      cobrança: a conta volta na hora, e o que estava no ar sobe
                      sozinho.
                beta_ending:
                  summary: beta_ending
                  value:
                    status: error
                    code: beta_ending
                    message: >-
                      Seu beta terminou e a conta está voltando ao plano Free.
                      Espere alguns minutos e tente de novo.
        '413':
          description: O arquivo passa de 4 GB, ou não cabe na cota do plano.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                file_too_large:
                  summary: file_too_large
                  value:
                    status: error
                    code: file_too_large
                    message: >-
                      Cada arquivo do Blob pode ter até 4 GB. Divida o arquivo
                      em partes menores e envie de novo.
                    maxBytes: 4294967296
                blob_quota_exceeded:
                  summary: blob_quota_exceeded
                  value:
                    status: error
                    code: blob_quota_exceeded
                    message: >-
                      Este arquivo (200 MB) não cabe no Blob do plano Block: 4,9
                      GB de 5 GB já estão ocupados. Apague arquivos que não usa
                      ou mude para um plano maior.
                    usedBytes: 5261334937
                    quotaBytes: 5368709120
                    sizeBytes: 209715200
        '429':
          description: Limite de pedidos. Traz o cabeçalho `Retry-After`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                rate_limit_exceeded:
                  summary: rate_limit_exceeded
                  value:
                    status: error
                    code: rate_limit_exceeded
                    message: >-
                      A sua conta passou do limite da API do plano Free: 10
                      pedidos por minuto. Espere 42 s e tente de novo.
                too_many_attempts:
                  summary: too_many_attempts
                  value:
                    status: error
                    code: too_many_attempts
                    message: Muitas tentativas. Tente de novo em 15 minutos.
        '503':
          description: O armazenamento do Blob não respondeu. Nada mudou.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                blob_unavailable:
                  summary: blob_unavailable
                  value:
                    status: error
                    code: blob_unavailable
                    message: >-
                      O Blob não está disponível agora. Tente de novo em
                      instantes.
      x-codeSamples:
        - lang: bash
          label: curl
          source: >-
            SIZE=$(wc -c < logo.png | tr -d ' ')

            UP=$(curl -s -X POST https://app.cubehosting.com.br/api/blob/objects
            \
              -H "Authorization: Bearer $CUBE_API_KEY" \
              -H "Content-Type: application/json" \
              -d "{\"path\": \"img/logo.png\", \"sizeBytes\": $SIZE, \"contentType\": \"image/png\"}")
            # O arquivo vai direto no link, sem a chave de API.

            curl -X PUT "$(echo "$UP" | jq -r .upload.url)" -H "Content-Type:
            image/png" --data-binary @logo.png

            curl -X POST https://app.cubehosting.com.br/api/blob/objects/$(echo
            "$UP" | jq -r .object.id)/complete \
              -H "Authorization: Bearer $CUBE_API_KEY"
        - lang: javascript
          label: Node.js
          source: >-
            import { readFile } from 'node:fs/promises';

            const API = 'https://app.cubehosting.com.br/api';

            const headers = { Authorization: `Bearer
            ${process.env.CUBE_API_KEY}` };


            const file = await readFile('logo.png');

            const res = await fetch(`${API}/blob/objects`, {
              method: 'POST',
              headers: { ...headers, 'Content-Type': 'application/json' },
              body: JSON.stringify({ path: 'img/logo.png', sizeBytes: file.length, contentType: 'image/png' }),
            });

            const { object, upload } = await res.json();

            // Direto no link, sem a chave de API.

            await fetch(upload.url, { method: 'PUT', headers: upload.headers,
            body: file });

            await fetch(`${API}/blob/objects/${object.id}/complete`, { method:
            'POST', headers });
        - lang: python
          label: Python
          source: >-
            import os

            import requests


            API = "https://app.cubehosting.com.br/api"

            headers = {"Authorization": f"Bearer {os.environ['CUBE_API_KEY']}"}


            size = os.path.getsize("logo.png")

            r = requests.post(
                f"{API}/blob/objects",
                headers=headers,
                json={"path": "img/logo.png", "sizeBytes": size, "contentType": "image/png"},
                timeout=30,
            )

            r.raise_for_status()

            up = r.json()

            # Direto no link, sem a chave de API.

            with open("logo.png", "rb") as f:
                requests.put(up["upload"]["url"], data=f, headers=up["upload"]["headers"], timeout=3600).raise_for_status()
            requests.post(f"{API}/blob/objects/{up['object']['id']}/complete",
            headers=headers, timeout=30).raise_for_status()
components:
  schemas:
    BlobUploadInput:
      type: object
      required:
        - path
        - sizeBytes
      properties:
        path:
          type: string
          description: >-
            O nome, com pastas por `/`: até 1024 bytes, sem `/` no começo ou no
            fim, sem pasta vazia, `.` ou `..`, sem `\`.
        sizeBytes:
          type: integer
          minimum: 0
          maximum: 4294967296
          description: 'O tamanho exato do arquivo: o link só aceita esse tamanho.'
        contentType:
          type: string
          description: >-
            O tipo (`image/png`), sem parâmetros; padrão
            `application/octet-stream`. O link só aceita esse tipo.
    BlobUpload:
      type: object
      required:
        - object
        - upload
      properties:
        object:
          $ref: '#/components/schemas/BlobObject'
        upload:
          type: object
          required:
            - url
            - method
            - headers
            - expiresAt
          properties:
            url:
              type: string
              format: uri
              description: O link do envio, direto no armazenamento (sem a chave de API).
            method:
              type: string
              enum:
                - PUT
            headers:
              type: object
              additionalProperties:
                type: string
              description: Os cabeçalhos que o `PUT` precisa mandar (o `content-type`).
            expiresAt:
              type: string
              format: date-time
              description: Até quando o `PUT` pode começar (15 minutos).
    Error:
      type: object
      required:
        - status
        - code
        - message
      properties:
        status:
          type: string
          const: error
        code:
          type: string
          description: Código fixo em inglês. Veja [Códigos de erro](/errors).
        message:
          type: string
          description: Texto em português para mostrar a uma pessoa.
      additionalProperties: true
    BlobObject:
      type: object
      required:
        - id
        - path
        - sizeBytes
        - contentType
        - status
        - createdAt
      properties:
        id:
          type: string
          description: ID do arquivo (26 caracteres).
        path:
          type: string
          description: O nome, com pastas por `/` (`img/logo.png`).
        sizeBytes:
          type: integer
        contentType:
          type: string
          description: O tipo mandado no envio (`application/octet-stream` sem ele).
        status:
          type: string
          enum:
            - pending
            - ready
          description: '`pending` até a confirmação do envio.'
        createdAt:
          type: string
          format: date-time
          description: Quando o envio foi confirmado.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Chave de API da Cube (`cube_…`), criada no painel em **Chaves de API**.
        Mande como `Authorization: Bearer cube_…`.

````