Criar Checkout

referência para integração (LLM / Cursor / Lovable)

External Checkout API — referência para integração (LLM / Cursor / Lovable)

Documento de contrato da API pública de criação de checkout com carrinho. Use ao gerar código, prompts ou integrações (Framer, Webflow, HTML, etc.).


Base URL (produção)

https://apiv3.usecorvex.com.br

Todas as URLs abaixo são relativas a essa base (sem barra final na base).


Contrato resumido (para copiar em prompts)

ItemValor
MétodoPOST
Path principal/stores/external/checkout
Path alternativo/api/stores/external/checkout (mesmo handler)
Header obrigatórioContent-Type: application/json
Header obrigatóriox-api-key: <valor copiado do painel Corvex em Configuração>
CorpoJSON; mínimo: cart.items[] com pelo menos 1 item
cart.tokenRecomendado: string única por carrinho do usuário; ver seção dedicada abaixo
PreçosInteiros em centavos (ex.: R$ 99,90 → 9990)
ImagemCada item deve ter image com URL absoluta http:// ou https:// válida

A chave x-api-key não deve ser construída manualmente: o lojista copia o valor já formatado no painel (Configuração).


Endpoints completos

POST https://apiv3.usecorvex.com.br/stores/external/checkout
POST https://apiv3.usecorvex.com.br/api/stores/external/checkout

Autenticação

  • Envie o header x-api-key com o valor fornecido no painel da Corvex (configuração da loja), já no formato correto.
  • Não envie storeId no body como fonte principal de identificação da loja; a loja é resolvida a partir dessa chave.

cart.token e checkoutId (não confundir)

ConceitoOnde apareceQuem defineRegra
cart.tokenBody (cart.token)Cliente (seu app)Deve ser único para cada carrinho do usuário (cada “sessão de carrinho” ou cada composição de itens que você trata como um carrinho novo). Sempre gere um valor novo com base no carrinho atual do usuário (ex.: ao montar o carrinho no front, ao sincronizar com o builder, ao serializar o estado do carrinho). Não reutilize o mesmo token para dois carrinhos diferentes. Se omitir, o servidor gera um fallback — o ideal é você enviar para rastreio e consistência.
checkoutIdResposta (checkoutId)Servidor CorvexUUID do checkout criado. Não vai no body do POST; use o retorno para abrir o link de pagamento (checkoutUrl).

Resumo para implementação: a cada vez que o usuário tem um carrinho que você vai transformar em checkout, gere um identificador exclusivo (ex.: crypto.randomUUID() no browser, ou hash estável dos itens + id de sessão) e envie em cart.token. Dois usuários ou dois carrinhos distintos nunca devem compartilhar o mesmo cart.token no mesmo sentido de negócio (um token = um carrinho lógico).


Body — payload mínimo (obrigatório)

Formato mínimo; inclua cart.token conforme a seção acima:

{
  "cart": {
    "token": "gerado-no-seu-app-unico-para-este-carrinho",
    "items": [
      {
        "title": "Nome do produto",
        "quantity": 1,
        "unitPrice": 9990,
        "image": "https://exemplo.com/imagem-do-produto.jpg"
      }
    ]
  }
}

Campos obrigatórios por item:

CampoTipoRegra
titlestringNão vazio; máx. 500 caracteres
quantitynumber inteiro≥ 1, ≤ 999
unitPricenumber inteiroCentavos; ≥ 0
imagestringURL absoluta válida (http/https); máx. 2000 caracteres

Body — campos opcionais (referência)

Use apenas quando o produto ou o fluxo exigir. O backend recalcula totais a partir dos itens quando os totais do carrinho não forem enviados.

cart

CampoTipoNotas
tokenstringIdentificador do carrinho no payload. Único por carrinho do usuário; sempre gerar no cliente com base no carrinho atual (ver seção cart.token e checkoutId). Máx. 200 caracteres. Se ausente, o servidor gera um token automático (ext_...).
currencystringPadrão BRL (único suportado na validação atual)
subtotalPrice, totalPrice, totalDiscountint (centavos)Opcionais; podem gerar avisos de coerência se divergirem do cálculo
requiresShippingbooleanPadrão true
discountsarrayObjetos: title, type (percentage | fixed | shipping), value, amount (centavos)
metadataobjectTamanho máximo total ~16KB (JSON serializado)

cart.items[] (além do mínimo)

CampoTipo
externalProductId, externalVariantId, sku, description, url, vendor, productTypestring
originalUnitPrice, discountedUnitPrice, linePrice, originalLinePrice, totalDiscountint (centavos)
requiresShippingboolean
options[{ "name", "value" }] (máx. 20)
metadataobject

Raiz do body

CampoTipo
customer{ name, email, phone, document } (strings ou null)
redirect{ successUrl, cancelUrl } (URLs ou null)
metadataobject

Resposta de sucesso — 201 Created

{
  "success": true,
  "checkoutId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "checkoutUrl": "https://.../pay/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "storeId": "uuid-da-loja",
  "cartToken": "valor-igual-ao-checkout.token-no-banco"
}
  • checkoutId: id do checkout na Corvex (único por criação de checkout).
  • cartToken: mesmo valor persistido em checkout.token — em geral o cart.token que você enviou; se você não enviou cart.token, será o token gerado pelo servidor (ex.: prefixo ext_).

O domínio de checkoutUrl pode ser o da loja (domínio customizado ativo) ou o padrão da Corvex, conforme configuração.

Respostas de erro (formato típico)

Todas usam success: false e objeto error com code e message. Validação Zod pode incluir details (estrutura aninhada).

400 — payload inválido

{
  "success": false,
  "error": {
    "code": "INVALID_PAYLOAD",
    "message": "Payload inválido",
    "details": {}
  }
}

Exemplos de causa: item sem title, sem image, URL de imagem inválida, quantity menor que 1, unitPrice inválido, carrinho vazio, metadata muito grande, etc. Os detalhes vêm em details quando for erro de validação Zod.

401 — chave ausente

{
  "success": false,
  "error": {
    "code": "MISSING_API_KEY",
    "message": "Header x-api-key é obrigatório"
  }
}

401 — chave inválida / não decodificável

{
  "success": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "API key inválida ou mal formatada"
  }
}

403 — loja inativa

{
  "success": false,
  "error": {
    "code": "STORE_INACTIVE",
    "message": "Loja está inativa"
  }
}

404 — loja não encontrada

{
  "success": false,
  "error": {
    "code": "STORE_NOT_FOUND",
    "message": "Loja não encontrada"
  }
}

500 — erro interno

{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "Erro interno ao processar checkout"
  }
}

Em ambiente não controlado pelo handler dedicado, erros genéricos do servidor podem retornar outro formato; trate status >= 400 e parse seguro de JSON.


cURL mínimo (produção)

Substitua SUA_CHAVE_DO_PAINEL pelo valor copiado em Configuração no painel Corvex.

curl -sS -X POST "https://apiv3.usecorvex.com.br/stores/external/checkout" \
  -H "Content-Type: application/json" \
  -H "x-api-key: SUA_CHAVE_DO_PAINEL" \
  -d "{\"cart\":{\"token\":\"uuid-ou-id-unico-do-carrinho\",\"items\":[{\"title\":\"Produto\",\"quantity\":1,\"unitPrice\":9990,\"image\":\"https://cdn.exemplo.com/foto.jpg\"}]}}"

Snippet fetch (browser / Lovable)

const API_BASE = "https://apiv3.usecorvex.com.br";
const API_KEY = import.meta.env.VITE_CORVEX_CHECKOUT_KEY; // ou variável do seu builder

const res = await fetch(`${API_BASE}/stores/external/checkout`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "x-api-key": API_KEY,
  },
  body: JSON.stringify({
    cart: {
      token: crypto.randomUUID(), // único por carrinho do usuário — gere sempre (ex.: ao montar o carrinho)
      items: [
        {
          title: "Produto",
          quantity: 1,
          unitPrice: 9990,
          image: "https://cdn.exemplo.com/foto.jpg",
        },
      ],
    },
  }),
});
const data = await res.json();
if (!res.ok || !data.success) throw new Error(data.error?.message || res.statusText);
window.location.href = data.checkoutUrl;

Limites úteis

LimiteValor
Itens por carrinho100
Quantidade por item999
Título do item500 caracteres
Descrição do item5000 caracteres
Metadata (aprox.)16KB por objeto relevante na validação
Preço máximo (centavos)Conforme validador do backend

Índice de códigos error.code

CódigoHTTP típico
MISSING_API_KEY401
INVALID_API_KEY401
STORE_NOT_FOUND404
STORE_INACTIVE403
INVALID_PAYLOAD400
INTERNAL_ERROR500

Outros códigos listados no tipo (EMPTY_CART, INVALID_ITEM, etc.) podem aparecer em evoluções futuras ou em camadas genéricas; o fluxo atual concentra falhas de validação em INVALID_PAYLOAD com details.