Corvex

Integrações

API de rastreio de pedidos

Contrato para WMS, ERP, Make e n8n atualizarem código de rastreio via API Key (orders:write).

API de Integração — Atualização de Rastreio de Pedidos

Documento de contrato para integrações externas (WMS, ERP, Make, n8n, scripts).

Base URL (produção)

https://apiv3.usecorvex.com.br

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


Visão geral

A Corvex oferece uma superfície dedicada para o lojista atualizar o código de rastreio dos pedidos via API Key, sem expor o JWT de sessão do painel.

ItemValor
Prefixo da API de integração/integrations/v1
AutenticaçãoAuthorization: Bearer cvx_live_...
Escopo obrigatórioorders:write
Restrição de lojastoreIds na chave (obrigatório para este escopo)
JWT do painelNão aceito nas rotas /integrations/v1/*

O que a API faz

  • Atualiza trackingCode, trackingUrl, trackingStatus e trackingCarrier no pedido.
  • Dispara o mesmo fluxo interno do painel (timeline de rastreio, automações tracking_code_updated, integrações Appmax/Reportana quando aplicável).
  • Aceita identificador do pedido como UUID interno ou external_id (referência externa do pedido na loja).

O que a API não faz

  • Não lista pedidos (use o painel ou outras rotas autenticadas por JWT).
  • Não cria pedidos.
  • Não aceita x-api-key do checkout externo (stores/external/checkout) — sistema diferente.

Fluxo recomendado

Fluxo: painel cria API Key → integração envia PATCH/POST com Bearer cvx_live_... → API retorna 200.

  1. No painel, com login + 2FA, crie uma API Key com escopo orders:write e a(s) loja(s) em storeIds.
  2. Guarde o plainKey — ele não é exibido novamente.
  3. Na integração, use apenas Authorization: Bearer cvx_live_... nas rotas /integrations/v1.

Autenticação

Header obrigatório

Authorization: Bearer cvx_live_ABCDEFGHIJKLMNOPQRSTUVWXYZ012345
Content-Type: application/json
  • Formato: cvx_live_ + 32 caracteres (base32 Crockford).
  • Não use x-api-key nesta API.
  • Não envie JWT de sessão do painel nas rotas /integrations/v1/*.

Criar API Key (painel / JWT apenas)

Esta rota exige token de sessão do painel. Uma API Key não pode criar outra API Key.

MétodoPath
POST/api-keys
GET/api-keys — listar chaves (sem secret)
DELETE/api-keys/:id — revogar
POST/api-keys/:id/rotate — rotacionar
GET/api-keys/_meta/scopes — listar escopos disponíveis

Exemplo — criar chave para rastreio

curl --request POST 'https://apiv3.usecorvex.com.br/api-keys' \
  --header 'Authorization: Bearer SEU_JWT_DO_PAINEL' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "WMS Rastreio",
    "scopes": ["orders:write"],
    "storeIds": ["909ed99c-a3a5-4e91-ba41-f4be59df8efb"],
    "neverExpires": true
  }'

Alternativa com expiração:

{
  "name": "WMS Rastreio",
  "scopes": ["orders:write"],
  "storeIds": ["909ed99c-a3a5-4e91-ba41-f4be59df8efb"],
  "expiresAt": "2027-08-28T12:00:00-03:00",
  "neverExpires": false
}

Resposta 201 — sucesso

{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "WMS Rastreio",
    "plainKey": "cvx_live_ABCDEFGHIJKLMNOPQRSTUVWXYZ012345",
    "prefix": "cvx_live_ABCDEFGHIJKL",
    "last4": "2345",
    "display": "cvx_live_ABCDEFGHIJKL…2345",
    "scopes": ["orders:write"],
    "storeIds": ["909ed99c-a3a5-4e91-ba41-f4be59df8efb"],
    "expiresAt": null,
    "createdAt": "2026-08-28T15:00:00.000Z",
    "notice": "Guarde esta chave agora. Ela NÃO será exibida novamente. Se perder, revogue e crie outra."
  }
}

Escopos disponíveis (referência)

EscopoUso
orders:writeAtualizar rastreio de pedidos (esta API)
stores:readListar lojas
themes:read / themes:write / themes:publishCLI de temas

Para orders:write, storeIds é obrigatório (ao menos uma loja UUID).


Endpoints de rastreio (integração)

MétodoPathDescrição
PATCH/integrations/v1/stores/:storeId/orders/:orderRef/trackingAtualiza um pedido
POST/integrations/v1/stores/:storeId/orders/tracking/bulkAtualiza até 100 pedidos

Parâmetros de rota

ParâmetroTipoDescrição
storeIdUUIDID da loja na Corvex. Deve estar em storeIds da chave.
orderRefstring (1–80)UUID do pedido ou external_id (ex.: PED-1001, #12345)

1. Atualizar rastreio de um pedido

Request

PATCH /integrations/v1/stores/{storeId}/orders/{orderRef}/tracking
Authorization: Bearer cvx_live_...
Content-Type: application/json

Body (JSON)

CampoTipoObrigatórioDescrição
trackingCodestring (1–120)SimCódigo de rastreio
trackingUrlstring (URL, max 2048)NãoLink de rastreamento
trackingStatusenumNãoStatus do ciclo de vida (ver tabela abaixo)
trackingCarrierstring (max 120)NãoTransportadora (ex.: Correios, Jadlog)

Status de rastreio (trackingStatus)

ValorDescrição típica
label_generatedEtiqueta gerada
postedPostado / enviado
in_transitEm trânsito
out_for_deliverySaiu para entrega
deliveredEntregue
failedFalha na entrega
returnedDevolvido
unknownStatus desconhecido

Exemplo — por UUID do pedido

export API_URL="https://apiv3.usecorvex.com.br"
export API_KEY="cvx_live_ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
export STORE_ID="909ed99c-a3a5-4e91-ba41-f4be59df8efb"
export ORDER_ID="11111111-1111-4111-8111-111111111111"

curl --request PATCH "${API_URL}/integrations/v1/stores/${STORE_ID}/orders/${ORDER_ID}/tracking" \
  --header "Authorization: Bearer ${API_KEY}" \
  --header "Content-Type: application/json" \
  --data '{
    "trackingCode": "AB123456789BR",
    "trackingUrl": "https://rastreamento.correios.com.br/app/index.php?objeto=AB123456789BR",
    "trackingStatus": "posted",
    "trackingCarrier": "Correios"
  }'

Exemplo — por external_id

curl --request PATCH "${API_URL}/integrations/v1/stores/${STORE_ID}/orders/PED-1001/tracking" \
  --header "Authorization: Bearer ${API_KEY}" \
  --header "Content-Type: application/json" \
  --data '{
    "trackingCode": "AB123456789BR"
  }'

Resposta 200 — sucesso

{
  "success": true,
  "message": "Código de rastreio atualizado com sucesso",
  "data": {
    "order": {
      "id": "11111111-1111-4111-8111-111111111111",
      "trackingCode": "AB123456789BR",
      "trackingUrl": "https://rastreamento.correios.com.br/app/index.php?objeto=AB123456789BR",
      "trackingStatus": "posted"
    }
  }
}

2. Atualizar rastreio em massa (bulk)

Processa até 100 pedidos por requisição. Cada item pode usar UUID ou external_id.

Request

POST /integrations/v1/stores/{storeId}/orders/tracking/bulk
Authorization: Bearer cvx_live_...
Content-Type: application/json

Body (JSON)

{
  "items": [
    {
      "orderId": "PED-1001",
      "trackingCode": "AB111111111BR",
      "trackingStatus": "posted",
      "trackingCarrier": "Correios"
    },
    {
      "orderId": "11111111-1111-4111-8111-111111111111",
      "trackingCode": "AB222222222BR",
      "trackingUrl": "https://tracking.example.com/AB222222222BR"
    }
  ]
}
Campo (item)TipoObrigatórioDescrição
orderIdstring (1–80)SimUUID ou external_id
trackingCodestring (1–120)SimCódigo de rastreio
trackingUrlstring (URL)NãoURL de rastreamento
trackingStatusenumNãoMesmos valores do PATCH individual
trackingCarrierstring (max 120)NãoTransportadora

Exemplo curl

curl --request POST "${API_URL}/integrations/v1/stores/${STORE_ID}/orders/tracking/bulk" \
  --header "Authorization: Bearer ${API_KEY}" \
  --header "Content-Type: application/json" \
  --data '{
    "items": [
      { "orderId": "PED-1001", "trackingCode": "AB111111111BR" },
      { "orderId": "PED-1002", "trackingCode": "AB222222222BR", "trackingStatus": "in_transit" }
    ]
  }'

Resposta 200 — todos atualizados

{
  "success": true,
  "message": "2 rastreio(s) atualizado(s)",
  "data": {
    "total": 2,
    "updated": 2,
    "skipped": 0,
    "failed": 0,
    "results": [
      {
        "index": 0,
        "orderId": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
        "orderReference": "PED-1001",
        "status": "updated",
        "trackingStatus": "posted"
      },
      {
        "index": 1,
        "orderId": "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
        "orderReference": "PED-1002",
        "status": "updated",
        "trackingStatus": "in_transit"
      }
    ]
  }
}

Resposta 200 — parcial (alguns falharam)

Quando failed > 0, success no corpo é false, mas o status HTTP continua 200 (processamento parcial).

{
  "success": false,
  "message": "1 rastreio(s) atualizado(s)",
  "data": {
    "total": 2,
    "updated": 1,
    "skipped": 0,
    "failed": 1,
    "results": [
      {
        "index": 0,
        "orderId": "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
        "orderReference": "PED-1001",
        "status": "updated",
        "trackingStatus": "posted"
      },
      {
        "index": 1,
        "orderId": "PED-9999",
        "orderReference": "PED-9999",
        "status": "failed",
        "reason": "order_not_found"
      }
    ]
  }
}

Status por item (results[].status)

StatusDescrição
updatedRastreio persistido ou automação notificada
skippedSem alteração (reason: no_change)
failedErro — ver reason

Reasons comuns em failed

reasonDescrição
order_not_foundPedido não existe nesta loja
invalid_tracking_codeCódigo inválido ou vazio após normalização

Respostas de erro (integração)

Formato pode variar entre rotas que usam FastifyAdapter (objeto error aninhado) e controllers diretos (error como string). Exemplos reais:

400 — validação do body

{
  "success": false,
  "message": "Dados inválidos",
  "errors": [
    {
      "code": "too_small",
      "minimum": 1,
      "type": "string",
      "message": "Código de rastreio é obrigatório",
      "path": ["trackingCode"]
    }
  ]
}

401 — sem credencial ou API Key inválida

{
  "success": false,
  "error": {
    "message": "Credencial inválida.",
    "code": "AUTH_API_KEY_INVALID"
  },
  "meta": {
    "timestamp": "2026-08-28T15:00:00.000Z",
    "status": 401
  }
}

401 — rota de integração sem API Key (JWT enviado por engano)

{
  "success": false,
  "error": {
    "message": "Esta rota exige uma API Key. Use Authorization: Bearer cvx_live_...",
    "code": "AUTH_API_KEY_REQUIRED"
  },
  "meta": {
    "timestamp": "2026-08-28T15:00:00.000Z",
    "status": 401
  }
}

401 — chave expirada / revogada

codeMensagem típica
AUTH_API_KEY_EXPIREDCredencial expirou
AUTH_API_KEY_REVOKEDCredencial revogada

403 — escopo insuficiente

{
  "success": false,
  "error": {
    "message": "Sua API Key não tem o escopo 'orders:write' necessário para esta operação.",
    "code": "AUTH_SCOPE_DENIED"
  },
  "meta": {
    "timestamp": "2026-08-28T15:00:00.000Z",
    "status": 403
  }
}

403 — loja não autorizada na chave

{
  "success": false,
  "message": "Esta API Key não tem acesso a esta loja.",
  "error": "AUTH_STORE_ACCESS_DENIED"
}

403 — permissão de pedidos insuficiente

Usuário da chave não é dono/membro com módulo PEDIDOS nível 2 (edição).

{
  "message": "Permissão insuficiente para esta ação",
  "code": "INSUFFICIENT_PERMISSION",
  "module": "PEDIDOS",
  "requiredLevel": 2,
  "currentLevel": 1
}

403 — faturas vencidas

{
  "success": false,
  "error": "Acesso bloqueado",
  "message": "Você possui faturas vencidas que precisam ser regularizadas",
  "reason": "<motivo do bloqueio>",
  "details": {}
}

404 — pedido não encontrado na loja

Não revela se o pedido existe em outra loja (anti-IDOR).

{
  "success": false,
  "message": "Pedido não encontrado nesta loja",
  "error": "ORDER_NOT_FOUND"
}

429 — rate limit

{
  "success": false,
  "message": "Muitas requisições. Tente novamente em instantes.",
  "error": "RATE_LIMITED",
  "retryAfter": 45
}

Header opcional: Retry-After: 45 (segundos).


Rate limits e proteções

Falhas de autenticação (qualquer rota com API Key)

DimensãoLimite
Por IP10 falhas / minuto
Por prefix da chave30 falhas / hora

Após excesso: 429 com RATE_LIMITED ou bloqueio temporário na auth.

Throughput de escrita (rastreio)

OperaçãoPor chave / minPor IP / minPor loja / min
PATCH individual60120200
POST bulk102030

Outras proteções

  • Chave restrita a storeIds definidos na criação.
  • Lookup de pedido sempre filtrado por storeId da URL.
  • Auditoria de uso da API Key (SCOPE_DENIED, STORE_DENIED, FAILED_AUTH, etc.).
  • Limite de 20 chaves ativas por usuário (padrão).

Segurança — boas práticas

  1. Crie uma chave só para integração — escopo mínimo (orders:write) e storeIds da loja certa.
  2. Não commite o plainKey em repositórios; use variáveis de ambiente ou secret manager.
  3. Rotacione (POST /api-keys/:id/rotate) se houver suspeita de vazamento.
  4. Revogue (DELETE /api-keys/:id) chaves antigas.
  5. Prefira /integrations/v1 em vez de expor JWT do painel em automações.

Rotas alternativas (painel / JWT)

O painel Corvex também expõe rotas legadas com JWT de sessão (e API Key com escopo orders:write):

MétodoPathAuth
PATCH/orders/:id/trackingJWT ou API Key + orders:write
POST/orders/stores/:storeId/tracking/bulkJWT ou API Key + orders:write

Para integrações externas, prefira /integrations/v1 — contrato estável e auth exclusiva por API Key.


Exemplo completo — script bash

#!/usr/bin/env bash
set -euo pipefail

API_URL="${CORVEX_API_URL:-https://apiv3.usecorvex.com.br}"
API_KEY="${CORVEX_API_KEY:?defina CORVEX_API_KEY}"
STORE_ID="${CORVEX_STORE_ID:?defina CORVEX_STORE_ID}"
ORDER_REF="${1:?usage: $0 <orderRef> <trackingCode>}"
TRACKING_CODE="${2:?usage: $0 <orderRef> <trackingCode>}"

curl --silent --show-error --fail-with-body \
  --request PATCH "${API_URL}/integrations/v1/stores/${STORE_ID}/orders/${ORDER_REF}/tracking" \
  --header "Authorization: Bearer ${API_KEY}" \
  --header "Content-Type: application/json" \
  --data "$(jq -n \
    --arg code "$TRACKING_CODE" \
    '{ trackingCode: $code, trackingStatus: "posted" }')"

Exemplo — Make / n8n

HTTP Request node:

  • Method: PATCH
  • URL: https://apiv3.usecorvex.com.br/integrations/v1/stores/{{storeId}}/orders/{{orderRef}}/tracking
  • Authentication: Header Authorization = Bearer {{apiKey}}
  • Body (JSON):
{
  "trackingCode": "{{trackingCode}}",
  "trackingUrl": "{{trackingUrl}}",
  "trackingStatus": "posted",
  "trackingCarrier": "Correios"
}

Para bulk, use POST em /orders/tracking/bulk com body { "items": [...] }.


Referência rápida de códigos de erro

HTTPCódigoCausa comum
400VALIDATION_ERRORBody inválido (Zod)
401AUTH_API_KEY_INVALIDChave incorreta
401AUTH_API_KEY_REQUIREDJWT em rota /integrations/v1
401AUTH_API_KEY_EXPIREDChave expirada
401AUTH_API_KEY_REVOKEDChave revogada
403AUTH_SCOPE_DENIEDFalta orders:write
403AUTH_STORE_ACCESS_DENIEDLoja fora de storeIds
403INSUFFICIENT_PERMISSIONSem PEDIDOS nível 2
404ORDER_NOT_FOUNDPedido inexistente na loja
429RATE_LIMITEDMuitas requisições
409API_KEY_LIMIT_REACHEDLimite de chaves ativas (criação)

Changelog

DataVersãoNotas
2026-08-28integrations/v1Primeira versão pública: escopo orders:write, PATCH + bulk, rate limits