Guia do Desenvolvedor

Modelos de Dados

Entenda as estruturas de dados que a API do Venddor retorna e como elas se relacionam.

Visao Geral

A API do Venddor retorna dados em formato JSON. Aqui estao os modelos de dados principais que voce vai encontrar ao integrar com a plataforma.

Todos os valores monetarios sao em centavos (int64). Todos os IDs sao UUIDs. Todos os timestamps sao ISO 8601 com timezone.

Produto

json
{
  "id": "550e8400-e29b-41d4-a716-446655440001",
  "name": "Camiseta Premium",
  "description": "Camiseta 100% algodao premium",
  "price_cents": 8990,
  "list_price_cents": 11990,
  "currency": "BRL",
  "sku": "SHIRT-001",
  "status": "A",
  "weight_grams": 250,
  "category_id": "550e8400-e29b-41d4-a716-446655440002",
  "vendor_id": "550e8400-e29b-41d4-a716-446655440003",
  "inventory_count": 150,
  "images": [
    {
      "id": "img_001",
      "url": "https://cdn.venddor.com.br/products/shirt-001.jpg",
      "alt": "Camiseta Premium frente",
      "position": 0
    }
  ],
  "variants": [
    {
      "id": "var_001",
      "name": "P",
      "sku": "SHIRT-001-P",
      "price_cents": 8990,
      "inventory_count": 50
    }
  ],
  "features": {
    "cor": "Azul",
    "tamanho": "P, M, G, GG",
    "material": "100% Algodao"
  },
  "seo": {
    "meta_title": "Camiseta Premium | Loja",
    "meta_description": "Camiseta premium de algodao...",
    "slug": "camiseta-premium"
  },
  "is_featured": false,
  "created_at": "2026-03-01T10:00:00Z",
  "updated_at": "2026-03-15T14:30:00Z"
}
CampoTipoDescrição
idUUIDIdentificador unico
price_centsint64Preco em centavos (8990 = R$89,90)
list_price_centsint64Preco de lista (antes do desconto)
statusstring"active" | "disabled" | "hidden"
weight_gramsintPeso em gramas (para calculo de frete)
inventory_countintQuantidade em estoque
featuresobjectCaracteristicas do produto (chave-valor)

Pedido

json
{
  "id": "ord_abc123",
  "order_number": "2026-0042",
  "status": "shipped",
  "customer": {
    "id": "usr_456",
    "name": "Joao Silva",
    "email": "joao@example.com",
    "phone": "+5511999998888"
  },
  "items": [
    {
      "product_id": "prod_789",
      "name": "Camiseta Premium",
      "sku": "SHIRT-001-M",
      "quantity": 2,
      "price_cents": 8990,
      "total_cents": 17980
    }
  ],
  "subtotal_cents": 17980,
  "shipping_cents": 1500,
  "discount_cents": 0,
  "tax_cents": 0,
  "total_cents": 19480,
  "currency": "BRL",
  "payment": {
    "method": "pix",
    "status": "paid",
    "paid_at": "2026-03-27T14:32:00Z"
  },
  "shipping": {
    "method": "correios_pac",
    "tracking_code": "BR123456789",
    "address": {
      "street": "Rua das Flores",
      "number": "123",
      "complement": "Apt 4B",
      "neighborhood": "Centro",
      "city": "Sao Paulo",
      "state": "SP",
      "zip": "01001-000",
      "country": "BR"
    }
  },
  "notes": "",
  "created_at": "2026-03-27T14:30:00Z",
  "updated_at": "2026-03-27T16:00:00Z"
}
StatusDescrição
pendingAguardando pagamento
paidPagamento confirmado
processingEm preparacao
shippedEnviado (com codigo de rastreio)
deliveredEntregue
cancelledCancelado
refundedReembolsado

Usuario / Cliente

json
{
  "id": "usr_456",
  "email": "joao@example.com",
  "name": "Joao Silva",
  "phone": "+5511999998888",
  "cpf": "123.456.789-00",
  "role": "customer",
  "is_active": true,
  "addresses": [
    {
      "id": "addr_001",
      "label": "Casa",
      "street": "Rua das Flores",
      "number": "123",
      "city": "Sao Paulo",
      "state": "SP",
      "zip": "01001-000",
      "is_default": true
    }
  ],
  "order_count": 5,
  "total_spent_cents": 89500,
  "last_order_at": "2026-03-27T14:30:00Z",
  "created_at": "2026-01-15T10:00:00Z"
}
Campos sensiiveis como CPF e telefone so sao retornados se seu app tem o escopo read_customers. O campo de senha nunca e retornado.

Categoria

json
{
  "id": "cat_001",
  "name": "Vestuario",
  "slug": "vestuario",
  "parent_id": null,
  "position": 1,
  "is_active": true,
  "product_count": 42,
  "children": [
    {
      "id": "cat_002",
      "name": "Camisetas",
      "slug": "camisetas",
      "parent_id": "cat_001",
      "position": 1,
      "product_count": 15
    }
  ],
  "seo": {
    "meta_title": "Vestuario",
    "meta_description": "Roupas e acessorios",
    "slug": "vestuario"
  }
}

Vendedor

json
{
  "id": "vendor_001",
  "name": "Loja do Joao",
  "slug": "loja-do-joao",
  "email": "joao@lojajoao.com.br",
  "cnpj": "12.345.678/0001-90",
  "status": "A",
  "logo_url": "https://cdn.venddor.com.br/vendors/logo.png",
  "product_count": 85,
  "rating": 4.7,
  "created_at": "2026-01-01T10:00:00Z"
}

Campo Status (CHAR(1))

Padronizado em 2026-05-21: todos os campos status na plataforma sao armazenados como uma unica letra maiuscula (PostgreSQL character(1)) e emitidos como uma string de uma letra. O alfabeto canonico abrange todos os dominios (produtos, pedidos, usuarios, vendedores, paginas, promocoes, pagamentos, envios, descontos, etc.).

CodigoSignificado
AActive
DDisabled
HHidden
PPending
RRejected
EExpired
FFailed
ICancelled
SShipped
CComplete
OOpen
ZChargeback
BBackordered
TTrialing

Cada dominio usa um subconjunto do alfabeto (por exemplo, produtos sao A/D/H, pedidos sao O/P/C/D/F/I/B/S/R/E/Z, usuarios sao A/D/N, vendedores sao A/D/N/P).

Compatibilidade retroativa: campos status em request bodies e query parameters tambem aceitam os rotulos longos legados ("active", "disabled", "pending", "hidden", etc.). Eles sao normalizados para a letra canonica na camada de servico. A saida e sempre a letra canonica — nunca o rotulo longo. Novas integracoes devem enviar a letra diretamente.
json
// Both of these are accepted on input — they produce the same record:
{ "status": "A" }
{ "status": "active" }

// But the API ALWAYS responds with the canonical letter:
// { "status": "A" }

Dinheiro em Centavos

TODOS os valores monetarios na API sao inteiros em centavos. Isso evita erros de arredondamento com ponto flutuante.

Valor realValor na APICalculo
R$ 0,0111 / 100 = 0.01
R$ 1,00100100 / 100 = 1.00
R$ 49,9049904990 / 100 = 49.90
R$ 1.299,99129999129999 / 100 = 1299.99
javascript
// Converting centavos to display format
function formatBRL(centavos) {
  return new Intl.NumberFormat('pt-BR', {
    style: 'currency',
    currency: 'BRL',
  }).format(centavos / 100);
}

// Examples:
formatBRL(4990);    // "R$ 49,90"
formatBRL(129999);  // "R$ 1.299,99"
formatBRL(0);       // "R$ 0,00"
NUNCA use float/double para calculos monetarios. Sempre opere com inteiros em centavos e converta para exibicao apenas na UI.

Identificadores UUID

Todos os recursos na API usam UUID v4 como identificador. UUIDs sao strings de 36 caracteres no formato:

text
550e8400-e29b-41d4-a716-446655440000

UUIDs sao preferidos sobre IDs sequenciais porque nao expoe quantidade de registros e sao seguros em ambiente multi-tenant.

Timestamps

Todos os timestamps sao em formato ISO 8601 com timezone UTC:

text
"created_at": "2026-03-27T14:30:00Z"
"updated_at": "2026-03-27T16:45:00Z"
javascript
// Parsing in JavaScript
const date = new Date(item.created_at);

// Display in Brazilian format
date.toLocaleDateString('pt-BR');  // "27/03/2026"
date.toLocaleTimeString('pt-BR');  // "14:30:00"

// Python
from datetime import datetime
date = datetime.fromisoformat(item['created_at'].replace('Z', '+00:00'))

Contexto Multi-Tenant

O Venddor e uma plataforma multi-tenant. Cada loja (tenant) tem seus proprios dados isolados. Ao chamar a API, voce sempre precisa especificar qual tenant esta acessando via header X-Tenant-ID.

O tenant_id e retornado durante o fluxo OAuth e deve ser armazenado junto com o access_token. Seu app pode ser instalado em multiplos tenants.

javascript
// Store per-tenant credentials
const tenantTokens = {
  'tenant-uuid-1': { accessToken: '...', refreshToken: '...' },
  'tenant-uuid-2': { accessToken: '...', refreshToken: '...' },
};

// Use the correct token for each tenant
async function callApi(tenantId, endpoint) {
  const { accessToken } = tenantTokens[tenantId];

  return fetch(`https://api.io.venddor.com.br${endpoint}`, {
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'X-Tenant-ID': tenantId,
    },
  });
}