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)
| Item | Valor |
|---|---|
| Método | POST |
| Path principal | /stores/external/checkout |
| Path alternativo | /api/stores/external/checkout (mesmo handler) |
| Header obrigatório | Content-Type: application/json |
| Header obrigatório | x-api-key: <valor copiado do painel Corvex em Configuração> |
| Corpo | JSON; mínimo: cart.items[] com pelo menos 1 item |
cart.token | Recomendado: string única por carrinho do usuário; ver seção dedicada abaixo |
| Preços | Inteiros em centavos (ex.: R$ 99,90 → 9990) |
| Imagem | Cada 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-keycom o valor fornecido no painel da Corvex (configuração da loja), já no formato correto. - Não envie
storeIdno body como fonte principal de identificação da loja; a loja é resolvida a partir dessa chave.
cart.token e checkoutId (não confundir)
cart.token e checkoutId (não confundir)| Conceito | Onde aparece | Quem define | Regra |
|---|---|---|---|
cart.token | Body (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. |
checkoutId | Resposta (checkoutId) | Servidor Corvex | UUID 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:
| Campo | Tipo | Regra |
|---|---|---|
title | string | Não vazio; máx. 500 caracteres |
quantity | number inteiro | ≥ 1, ≤ 999 |
unitPrice | number inteiro | Centavos; ≥ 0 |
image | string | URL 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
| Campo | Tipo | Notas |
|---|---|---|
token | string | Identificador 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_...). |
currency | string | Padrão BRL (único suportado na validação atual) |
subtotalPrice, totalPrice, totalDiscount | int (centavos) | Opcionais; podem gerar avisos de coerência se divergirem do cálculo |
requiresShipping | boolean | Padrão true |
discounts | array | Objetos: title, type (percentage | fixed | shipping), value, amount (centavos) |
metadata | object | Tamanho máximo total ~16KB (JSON serializado) |
cart.items[] (além do mínimo)
| Campo | Tipo |
|---|---|
externalProductId, externalVariantId, sku, description, url, vendor, productType | string |
originalUnitPrice, discountedUnitPrice, linePrice, originalLinePrice, totalDiscount | int (centavos) |
requiresShipping | boolean |
options | [{ "name", "value" }] (máx. 20) |
metadata | object |
Raiz do body
| Campo | Tipo |
|---|---|
customer | { name, email, phone, document } (strings ou null) |
redirect | { successUrl, cancelUrl } (URLs ou null) |
metadata | object |
Resposta de sucesso — 201 Created
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 emcheckout.token— em geral ocart.tokenque você enviou; se você não envioucart.token, será o token gerado pelo servidor (ex.: prefixoext_).
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
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
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
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
403 — loja inativa{
"success": false,
"error": {
"code": "STORE_INACTIVE",
"message": "Loja está inativa"
}
}404 — loja não encontrada
404 — loja não encontrada{
"success": false,
"error": {
"code": "STORE_NOT_FOUND",
"message": "Loja não encontrada"
}
}500 — erro interno
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
| Limite | Valor |
|---|---|
| Itens por carrinho | 100 |
| Quantidade por item | 999 |
| Título do item | 500 caracteres |
| Descrição do item | 5000 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
error.code| Código | HTTP típico |
|---|---|
MISSING_API_KEY | 401 |
INVALID_API_KEY | 401 |
STORE_NOT_FOUND | 404 |
STORE_INACTIVE | 403 |
INVALID_PAYLOAD | 400 |
INTERNAL_ERROR | 500 |
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.