Ao implementar recursos de geração de imagens e retoque localizado (inpainting) em aplicações web modernas, desenvolvedores solo e equipes enxutas frequentemente enfrentam um dilema complexo de infraestrutura. De um lado, auto-hospedar modelos abertos de difusão em instâncias dedicadas com GPU (como AWS EC2 G5, RunPod ou Modal) acarreta alta sobrecarga operacional: configuração de drivers CUDA, atualizações de dependências vLLM/Diffusers, latência de inicialização a frio e um piso de custo fixo entre 150 e 400 dólares mensais por hardware ocioso. Do outro lado, plataformas comerciais de SaaS (como Midjourney ou Leonardo) exigem assinaturas mensais fixas e planos fechados com créditos que expiram, gerando desperdício em produtos com tráfego variável.
O Dezgo resolve esse problema oferecendo uma API REST sem servidor sustentada por um modelo financeiro genuinamente pré-pago e sob demanda (pay-as-you-go). Com uma recarga inicial a partir de 10 dólares cujos créditos nunca expiram, desenvolvedores podem renderizar imagens Stable Diffusion de 512x512 pixels por cerca de 0,0019 dólares cada, com cobranças proporcionais calculadas de forma transparente com base na resolução e nos passos de amostragem.
Este guia prático orienta engenheiros full stack e backend na implementação de uma integração robusta com o Dezgo: autenticação via X-Dezgo-Key, consumo dos endpoints /text2image e /inpainting_sdxl, monitoramento de saldo em tempo real por meio de cabeçalhos HTTP e orquestração de filas assíncronas para evitar gargalos de timeout.
Comparativo de Arquitetura: GPUs Próprias vs. SaaS Tradicional vs. Dezgo
Antes de codificar, vale avaliar como as opções disponíveis se comportam em termos de custos e operação:
| Critério | Instâncias GPU Próprias (EC2 / RunPod) | SaaS Comercial Fechado (Midjourney) | API REST do Dezgo |
|---|---|---|---|
| Custo Mínimo Fixo | Elevado ($150–$500+/mês em capacidade ociosa) | Médio-Alto ($10–$60+/mês por usuário ativo) | Zero ($10 de recarga pré-paga única sem mensalidade) |
| Custo Unitário | Variável; oneroso durante vales de tráfego | Pacotes fixos; créditos não usados expiram | ~$0,0019 por imagem 512px; cálculo por passo e pixel |
| Carga de Manutenção | Alta (drivers, vazamento de memória e escala) | Mínima (plataforma fechada sem controle) | Mínima (requisições HTTP REST padrão; sem gerenciar GPU) |
| Suporte a Modelos | Total (qualquer checkpoint HuggingFace ou LoRA) | Baixo (restrito a modelos proprietários) | Alto (SD 1.5, SD 2.1, SDXL, Lightning e LoRAs) |
| Formato de Retorno | Exige desenvolvimento de protocolo próprio | Bots de Discord ou polling não padronizado | Stream binário direto (image/png) no corpo HTTP |
O principal diferencial do Dezgo é entregar a imagem diretamente como arquivo binário na resposta HTTP, acompanhada de metadados financeiros detalhados em cabeçalhos dedicados.
Autenticação e Arquitetura de Segurança
Todas as chamadas à API do Dezgo devem conter a chave de autenticação informada no cabeçalho HTTP X-Dezgo-Key. O token é gerado no painel da sua conta em dezgo.com/account.
Regra Fundamental: Nunca Chame o Dezgo Diretamente do Frontend
Como as chaves do Dezgo debitam diretamente do saldo em dinheiro pré-pago da sua conta e não possuem permissões restritas para usuários finais, expor o valor de X-Dezgo-Key no navegador ou em scripts do cliente representa um risco financeiro severo. Qualquer usuário mal-intencionado poderá interceptar o token e esgotar seu saldo em poucos minutos.
A arquitetura recomendada exige que todas as requisições passem por um servidor backend confiável ou API proxy:
[Navegador do Usuário]
│
│ 1. POST /api/generate (Sessão / Token JWT / Cota interna)
▼
[Backend da sua Aplicação]
│
│ 2. Validação de dados, dedução de créditos da aplicação
│ 3. Injeção do cabeçalho secreto "X-Dezgo-Key"
│ 4. POST https://api.dezgo.com/text2image
▼
[Motor REST do Dezgo]
│
│ 5. Retorno de stream PNG binário + cabeçalhos de custo
▼
[Backend da sua Aplicação]
│
│ 6. Leitura de x-dezgo-job-amount-usd e x-dezgo-balance-total-usd
│ 7. Upload para Object Storage (S3 / R2) ou stream para o cliente
▼
[Navegador do Usuário]
Passo 1: Integração de Text-to-Image (/text2image)
O endpoint de geração a partir de texto aceita requisições no formato multipart/form-data ou application/json (com imagens em base64) e retorna o arquivo de imagem diretamente como stream binário (image/png ou image/jpeg).
Parâmetros Principais da Requisição
prompt(string, obrigatório): Descrição em texto detalhando a imagem desejada.negative_prompt(string, opcional): Termos que devem ser evitados na imagem gerada.model(string, opcional): Identificador do modelo de difusão. Pode ser consultado emGET https://api.dezgo.com/info(comostablediffusion_1_5,stablediffusion_2_1_768px, etc.).guidance(número, opcional): Escala de fidelidade ao prompt (CFG Scale), usualmente entre 6.0 e 9.0 (padrão 7.5).steps(inteiro, opcional): Passos de amostragem de desnoising (normalmente de 20 a 50). Valores mais altos elevam a nitidez, mas aumentam proporcionalmente o custo.sampler(string, opcional): Algoritmo de amostragem (por exemplo,euler_a,ddim,dpmpp_2m).width/height(inteiro, opcional): Dimensões da imagem em pixels (padrão 512x512).
Exemplo de Implementação Backend em Node.js / TypeScript
// server/services/dezgoService.ts
import { Buffer } from "node:buffer";
interface TextToImageOptions {
prompt: string;
negativePrompt?: string;
model?: string;
guidance?: number;
steps?: number;
width?: number;
height?: number;
}
interface GenerationResult {
imageBuffer: Buffer;
contentType: string;
jobCostUsd: number;
remainingBalanceUsd: number;
}
export async function generateTextToImage(
options: TextToImageOptions
): Promise<GenerationResult> {
const apiKey = process.env.DEZGO_API_KEY;
if (!apiKey) {
throw new Error("A variável de ambiente DEZGO_API_KEY não foi configurada.");
}
const formData = new FormData();
formData.append("prompt", options.prompt);
if (options.negativePrompt) {
formData.append("negative_prompt", options.negativePrompt);
}
if (options.model) {
formData.append("model", options.model);
}
if (options.guidance) {
formData.append("guidance", options.guidance.toString());
}
if (options.steps) {
formData.append("steps", options.steps.toString());
}
if (options.width) {
formData.append("width", options.width.toString());
}
if (options.height) {
formData.append("height", options.height.toString());
}
const response = await fetch("https://api.dezgo.com/text2image", {
method: "POST",
headers: {
"X-Dezgo-Key": apiKey,
},
body: formData,
});
if (!response.ok) {
const errorBody = await response.text();
handleDezgoError(response.status, errorBody);
}
// Leitura de metadados financeiros contidos nos cabeçalhos de resposta
const jobCostUsd = parseFloat(
response.headers.get("x-dezgo-job-amount-usd") || "0"
);
const remainingBalanceUsd = parseFloat(
response.headers.get("x-dezgo-balance-total-usd") || "0"
);
const arrayBuffer = await response.arrayBuffer();
const imageBuffer = Buffer.from(arrayBuffer);
const contentType = response.headers.get("content-type") || "image/png";
return {
imageBuffer,
contentType,
jobCostUsd,
remainingBalanceUsd,
};
}
function handleDezgoError(status: number, message: string): never {
switch (status) {
case 400:
throw new Error(`Requisição inválida no Dezgo (400): ${message}`);
case 401:
throw new Error("Falha de autenticação no Dezgo (401): Verifique X-Dezgo-Key.");
case 402:
throw new Error("Saldo insuficiente no Dezgo (402): Saldo pré-pago esgotado.");
case 429:
throw new Error("Limite de taxa excedido no Dezgo (429): Muitas chamadas simultâneas.");
default:
throw new Error(`Erro do servidor Dezgo (${status}): ${message}`);
}
}
Passo 2: Integração de SDXL Inpainting (/inpainting_sdxl)
O inpainting permite substituir partes específicas de uma imagem através de uma máscara demarcada, mantendo o restante da composição preservado. O Dezgo oferece o endpoint /inpainting para modelos convencionais e /inpainting_sdxl para Stable Diffusion XL em altas resoluções.
Especificações das Imagens de Entrada
Para efetuar o inpainting, é necessário enviar dois arquivos:
init_image: A imagem base original a ser modificada (PNG ou JPEG).mask_image: Uma máscara monocromática com as dimensões idênticas às deinit_image. Áreas brancas (#FFFFFF) indicam onde o modelo deve pintar novos elementos, enquanto áreas pretas (#000000) preservam os pixels originais.
Exemplo de Implementação Backend em Python (FastAPI / Requests)
# app/services/dezgo_inpainting.py
import os
import requests
from typing import Dict, Any, Tuple
DEZGO_API_KEY = os.environ.get("DEZGO_API_KEY")
INPAINTING_SDXL_URL = "https://api.dezgo.com/inpainting_sdxl"
def execute_sdxl_inpainting(
prompt: str,
init_image_bytes: bytes,
mask_image_bytes: bytes,
negative_prompt: str = "",
guidance: float = 7.5,
steps: int = 30,
) -> Tuple[bytes, Dict[str, Any]]:
"""
Submete uma solicitação de inpainting SDXL ao Dezgo via multipart/form-data.
"""
if not DEZGO_API_KEY:
raise ValueError("A variável DEZGO_API_KEY não foi encontrada no ambiente.")
headers = {
"X-Dezgo-Key": DEZGO_API_KEY
}
files = {
"init_image": ("init.png", init_image_bytes, "image/png"),
"mask_image": ("mask.png", mask_image_bytes, "image/png"),
}
data = {
"prompt": prompt,
"negative_prompt": negative_prompt,
"guidance": str(guidance),
"steps": str(steps),
}
response = requests.post(
INPAINTING_SDXL_URL,
headers=headers,
files=files,
data=data,
timeout=60
)
if response.status_code == 402:
raise RuntimeError("Saldo pré-pago no Dezgo esgotado. Recarga necessária.")
elif response.status_code != 200:
raise RuntimeError(f"Erro no inpainting do Dezgo [{response.status_code}]: {response.text}")
metadata = {
"job_cost_usd": float(response.headers.get("x-dezgo-job-amount-usd", "0")),
"remaining_balance_usd": float(response.headers.get("x-dezgo-balance-total-usd", "0")),
"content_type": response.headers.get("Content-Type", "image/png"),
}
return response.content, metadata
Passo 3: Fluxos Assíncronos e Prevenção de Timeout em Aplicações Web
A API do Dezgo opera de modo síncrono, mantendo a conexão HTTP aberta até que o processamento do modelo seja concluído (geralmente entre 2 e 8 segundos). Em infraestruturas serverless com limites rígidos de execução (como o teto padrão de 10 segundos no tier gratuito da Vercel), requisições diretas podem sofrer timeouts de gateway.
Arquitetura com Fila Redis e Notificações por SSE
Em ambientes de produção, desacopla-se a requisição do usuário do processamento de imagem por meio de filas gerenciadas pelo Redis (como BullMQ no Node.js ou Celery no Python):
[Cliente Web] ── 1. POST /api/jobs (prompt e máscara) ──► [Servidor Web API]
│
▼
[Cliente Web] ◄─ 3. Retorna 202 Accepted { jobId } ─── 2. Enfileira no Redis
│ │
│ ▼
│ 4. Aguarda via SSE / WebSocket ou polling [Fila Redis / BullMQ]
│ │
│ ▼ 5. Consome tarefa
│ [Worker em Background]
│ │
│ ├── 6. Chama API Dezgo
│ ├── 7. Grava no S3 / R2
│ └── 8. Atualiza DB
◄── 9. Notifica conclusão com URL da imagem no CDN ──────┘
Código do Worker com BullMQ
// workers/renderWorker.ts
import { Worker, Job } from "bullmq";
import { generateTextToImage } from "../services/dezgoService";
import { uploadToS3 } from "../services/storageService";
import { db } from "../services/db";
export const renderWorker = new Worker("image-generation-queue", async (job: Job) => {
const { prompt, userId, jobId } = job.data;
// 1. Processa geração no Dezgo
const { imageBuffer, contentType, jobCostUsd, remainingBalanceUsd } =
await generateTextToImage({ prompt, steps: 30 });
// 2. Armazena a imagem no bucket S3 ou Cloudflare R2
const cdnUrl = await uploadToS3({
key: `renders/${userId}/${jobId}.png`,
body: imageBuffer,
contentType,
});
// 3. Atualiza registro na base de dados
await db.jobs.update({
where: { id: jobId },
data: {
status: "COMPLETED",
outputUrl: cdnUrl,
costUsd: jobCostUsd,
},
});
// 4. Emite alerta se o saldo pré-pago estiver baixo
if (remainingBalanceUsd < 5.0) {
console.warn(`[Aviso Financeiro] Saldo do Dezgo reduzido: restam $${remainingBalanceUsd.toFixed(2)}.`);
}
return { cdnUrl, jobCostUsd };
});
Gerenciamento de Saldo e Boas Práticas Operacionais
O Dezgo não possui cobrança automática com recarga automática por cartão de crédito. Os créditos devem ser adicionados manualmente pelo painel de controle antes que a conta chegue a zero. Por isso, acompanhar as métricas das respostas HTTP é crucial para manter a estabilidade do sistema.
Informações Contábeis nos Cabeçalhos HTTP
Em cada resposta bem-sucedida, o Dezgo retorna as seguintes informações:
x-dezgo-job-amount-usd: Valor cobrado especificamente por esta renderização.x-dezgo-balance-total-usd: Saldo restante atualizado da conta em dólares.x-dezgo-balance-credits-usd: Total histórico acumulado de depósitos realizados.x-dezgo-balance-debits-usd: Total histórico acumulado de consumo faturado.x-dezgo-balance-index: Contador sequencial do livro contábil da conta.
Verificação de Saldo Sem Renderizar Imagens
Para consultar o saldo atual sem disparar processamento nem gastar créditos, utilize o endpoint de transações:
curl -s -H "X-Dezgo-Key: YOUR_API_KEY" https://api.dezgo.com/account/tx/last
Essa requisição retorna um payload JSON contendo o índice da última transação e o valor atual do campo balance.
Resoluções de Erros Comuns
- HTTP 402 (Payment Required): O saldo pré-pago foi zerado. Capture este status no backend para disparar alertas urgentes para a equipe e apresentar uma mensagem clara ao usuário final ("Geração em fila por manutenção"), prevenindo erros genéricos 500.
- HTTP 429 (Too Many Requests): Limite de chamadas simultâneas atingido. Implemente lógica de retry com backoff exponencial no worker (ex.: 1s, 2s, 4s).
- HTTP 400 (Bad Request): Normalmente causado por divergência na proporção entre imagem base e máscara. Valide sempre as dimensões em pixels antes de despachar a chamada para o Dezgo.
Conclusão
Para desenvolvedores independentes e produtos com orçamento enxuto, o Dezgo elimina os altos custos fixos de manter GPUs ociosas e as restrições contratuais de assinaturas mensais fechadas. Estruturando uma camada de backend segura, um mecanismo de fila assíncrona e rotinas de monitoramento de saldo via cabeçalhos, é possível entregar geração de imagens sob demanda com excelente estabilidade e custos unitários abaixo de um centavo por imagem.