Enviando imagens pela API com direct upload

Alguns cadastros aceitam o envio de imagens — por exemplo, o campo image em ProductInput. O envio não é feito diretamente na mutation GraphQL: o arquivo vai para uma URL pré-assinada, e a mutation recebe apenas um identificador assinado (signed_id) que referencia o arquivo já armazenado.

Fluxo geral

1. Cliente  ──POST metadata──▶  /api/v1/blobs            (Fácil123)
                  ◀── { signed_id, direct_upload: { url, headers } } ──

2. Cliente  ──PUT bytes──────▶  direct_upload.url        (URL pré-assinada)

3. Cliente  ──mutation com signed_id──▶  /graphql        (Fácil123)

Passo 1 — Criar o blob

Faça um POST para /api/v1/blobs enviando os metadados do arquivo. O endpoint exige o mesmo Authorization: Bearer da API GraphQL.

Request:

curl -X POST https://app.facil123.com.br/api/v1/blobs \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer SEU_TOKEN_AQUI" \
  -d '{
    "blob": {
      "filename": "produto.png",
      "content_type": "image/png",
      "byte_size": 12345,
      "checksum": "1B2M2Y8AsgTpgAmY7PhCfg=="
    }
  }'
Campo Descrição
filename Nome original do arquivo.
content_type MIME type (ex.: image/png, image/jpeg).
byte_size Tamanho do arquivo em bytes.
checksum MD5 do conteúdo, codificado em Base64 (não hex).

Response (resumida):

{
  "signed_id": "eyJ...--abc123",
  "direct_upload": {
    "url": "https://upload.example.com/abc123",
    "headers": {
      "Content-Type": "image/png",
      "Content-MD5": "1B2M2Y8AsgTpgAmY7PhCfg=="
    }
  }
}

Passo 2 — Enviar o arquivo para a URL pré-assinada

Use a direct_upload.url retornada e envie o arquivo via PUT, com exatamente os headers devolvidos no passo 1. Não envie Authorization aqui — a URL já é pré-assinada.

curl -X PUT "https://upload.example.com/abc123" \
  -H "Content-Type: image/png" \
  -H "Content-MD5: 1B2M2Y8AsgTpgAmY7PhCfg==" \
  --data-binary @produto.png

A resposta de sucesso é 200 OK sem corpo. A partir desse momento o signed_id referencia um blob válido no Fácil123.

Passo 3 — Usar o signed_id na mutation

Passe o signed_id no campo correspondente do input. Em ProductInput, o campo é image:

curl -X POST https://app.facil123.com.br/graphql \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer SEU_TOKEN_AQUI" \
  -d '{
    "query": "mutation($attributes: ProductInput!) { createProduct(attributes: $attributes) { id name image } }",
    "variables": {
      "attributes": {
        "name": "Camiseta",
        "code": "CAM-001",
        "unit_id": "1",
        "kind": "mercadoria_para_revenda",
        "image": "eyJ...--abc123"
      }
    }
  }'

Os campos unit_id e kind são obrigatórios em createProduct. Use getUnits para descobrir os IDs disponíveis e o enum ProductKind para os tipos válidos — veja Explorando a API por introspecção.

O servidor associa o blob ao registro e, nas leituras seguintes, o campo image retorna a URL pública da imagem.

Acessando a imagem depois

O campo image em respostas de leitura retorna uma URL pública estável servida pelo Fácil123. Esse endpoint não exige token e responde com um redirect (302) para a URL pré-assinada real. A URL pré-assinada tem expiração curta — sempre referencie o blob pela URL do Fácil123, que é estável.

Observações

  • O endpoint /api/v1/blobs aceita qualquer tipo de arquivo (não só imagens). Restrições de formato são aplicadas pelo campo de destino na mutation.
  • O checksum deve ser o MD5 do conteúdo em Base64. Em Node, por exemplo: crypto.createHash('md5').update(buffer).digest('base64').