Pedidos
Registre pedidos que baixam o estoque na hora, liste e consulte pedidos e mova cada um pelas etapas até a entrega.
Um pedido criado pela API entra no Vamo como uma venda confirmada: o estoque dos produtos do catálogo baixa no mesmo instante, o pedido aparece nos pedidos do contato no Vamo e conta no total gasto dele.
Dinheiro em centavos
Todos os valores são inteiros em centavos (×100). R$ 4.599,00 vai como 459900; Gs. 150.000 vai como 15000000.
POST /orders
Cria um pedido para um contato. Acesso: chave secreta com Leitura e escrita.
Cabeçalho opcional: Idempotency-Key, até 200 caracteres (veja Repetir com segurança).
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
storeId | string (UUID) | Sim | A sua loja |
contactId | string (UUID) | Sim | Quem comprou |
conversationId | string (UUID) | Não | A conversa de onde veio a venda |
currency | string | Não | BRL, PYG ou USD. Padrão: a moeda dos produtos do catálogo; sem produtos do catálogo, a moeda principal da organização |
notes | string | Não | Observações (endereço, horário de entrega…) |
items | array | Sim | Pelo menos um item |
Cada item:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
productName | string | Sim | Nome do item. Num item do catálogo, o pedido grava o nome do catálogo no lugar |
quantity | inteiro | Sim | 1 ou mais |
unitPrice | inteiro | Sim | Preço unitário em centavos. Num item do catálogo, substitui o preço do catálogo |
productId | string (UUID) | Não | Um produto da loja. Com ele, o item baixa estoque |
variantId | string (UUID) | Não | Uma variação desse productId. Obrigatório quando o produto tem variações |
Um item sem productId é avulso (frete, instalação, embalagem para presente): entra no total e não mexe no estoque.
curl -X POST https://vamo.ai/api/v1/orders \
-H "Authorization: Bearer sk_live_SUA_CHAVE" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: site-pedido-1042" \
-d '{
"storeId": "7b1e2c3d-4a5f-4b6c-8d7e-9f0a1b2c3d4e",
"contactId": "2c9d8e7f-6a5b-4c3d-9e2f-1a0b9c8d7e6f",
"notes": "Entregar depois das 18h",
"items": [
{
"productId": "4d5e6f70-8192-4a3b-9c4d-5e6f708192a3",
"variantId": "6f708192-a3b4-4c5d-8e6f-708192a3b4c5",
"productName": "iPhone 15",
"quantity": 1,
"unitPrice": 459900
},
{ "productName": "Frete", "quantity": 1, "unitPrice": 2500 }
]
}'Resposta 201
{
"data": {
"id": "8192a3b4-c5d6-4e7f-9a8b-92a3b4c5d6e7",
"storeId": "7b1e2c3d-4a5f-4b6c-8d7e-9f0a1b2c3d4e",
"contactId": "2c9d8e7f-6a5b-4c3d-9e2f-1a0b9c8d7e6f",
"conversationId": null,
"total": 462400,
"currency": "BRL",
"status": "confirmed",
"source": "api",
"notes": "Entregar depois das 18h",
"needsReview": false,
"externalOrderId": null,
"reservationExpiresAt": null,
"createdAt": "2026-10-31T14:10:00.000Z",
"updatedAt": "2026-10-31T14:10:00.000Z",
"items": [
{
"id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"productId": "4d5e6f70-8192-4a3b-9c4d-5e6f708192a3",
"productName": "iPhone 15",
"variantId": "6f708192-a3b4-4c5d-8e6f-708192a3b4c5",
"variantName": "128 GB Azul",
"quantity": 1,
"unitPrice": 459900,
"total": 459900
},
{
"id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
"productId": null,
"productName": "Frete",
"variantId": null,
"variantName": null,
"quantity": 1,
"unitPrice": 2500,
"total": 2500
}
]
}
}Dispara o webhook order.created, com o pedido e os itens.
Estoque
- Tudo ou nada. Cada produto do catálogo precisa ser da loja, estar ativo e ter estoque para a quantidade pedida (somando itens repetidos). Se um item falhar, nenhum pedido é criado e nenhum estoque muda.
- Na hora e sem vender duas vezes. O estoque baixa junto com a criação do pedido. Se outra venda levou a última unidade um instante antes, o seu pedido responde
409 out_of_stock. - Variações. Num produto com variações (cor, memória, tamanho), cada item indica a variação em
variantId, e é o estoque dela que baixa. SemvariantId:400 variant_required. - Estoque que a loja não conta. Um produto marcado só como "em estoque" ou "sem estoque" (sem quantidade) vende qualquer quantidade enquanto estiver em estoque, e nada é baixado.
- Catálogo do WhatsApp. Quando o estoque muda, o catálogo do WhatsApp da loja é atualizado em seguida.
Diferenças para os pedidos da IA
| Pedido da API | Pedido da IA | |
|---|---|---|
| Status inicial | confirmed | confirmed, ou pending quando precisa de aprovação |
| Prazo de reserva | Não tem: o pedido não expira | Expira se não for pago no prazo (veja Pedidos e reservas) |
| Preço | O unitPrice que você enviar | O do catálogo, com o desconto combinado dentro do limite |
| Vai para a loja conectada (Shopify, WooCommerce) | Não | Sim, quando a integração está configurada para enviar pedidos |
Repetir com segurança
Uma falha de rede no meio do caminho deixa a dúvida: o pedido foi criado? Envie sempre o cabeçalho Idempotency-Key com um valor único por venda (o número do pedido no seu sistema, por exemplo). Repetindo a requisição com a mesma chave, o Vamo não cria outro pedido nem baixa o estoque de novo: responde 200 com o pedido que já existe, sem disparar outro webhook. Isso vale mesmo que o corpo seja diferente.
A chave vale só dentro da sua organização. Mais de 200 caracteres: 400 invalid_idempotency_key.
GET /orders
Lista os pedidos, do mais novo para o mais antigo, sem os itens. Acesso: chave secreta (leitura).
| Parâmetro | Descrição |
|---|---|
status | pending, confirmed, shipped, delivered ou cancelled |
contactId | Só os pedidos desse contato |
page, pageSize | Padrão 50, máximo 100 |
curl "https://vamo.ai/api/v1/orders?status=confirmed&contactId=2c9d8e7f-6a5b-4c3d-9e2f-1a0b9c8d7e6f" \
-H "Authorization: Bearer sk_live_SUA_CHAVE"Responde { "data": [ … ], "pagination": { … } }.
GET /orders/:id
Um pedido com os itens, no mesmo formato da criação. Acesso: chave secreta (leitura). 404 (Order not found) se não existir na sua organização.
curl https://vamo.ai/api/v1/orders/8192a3b4-c5d6-4e7f-9a8b-92a3b4c5d6e7 \
-H "Authorization: Bearer sk_live_SUA_CHAVE"source diz quem criou: ai (o agente de IA), human (a equipe no painel), api, ou null em pedidos antigos.
PATCH /orders/:id
Muda o status ou as observações. Acesso: chave secreta com Leitura e escrita.
| Campo | Descrição |
|---|---|
status | pending, confirmed, shipped, delivered ou cancelled |
notes | Observações (até 2.000 caracteres) |
Pelo menos um dos dois.
curl -X PATCH https://vamo.ai/api/v1/orders/8192a3b4-c5d6-4e7f-9a8b-92a3b4c5d6e7 \
-H "Authorization: Bearer sk_live_SUA_CHAVE" \
-H "Content-Type: application/json" \
-d '{ "status": "shipped" }'Responde 200 com o pedido (sem os itens) e dispara order.updated.
As etapas
Um pedido anda uma etapa por vez e pode ser cancelado até ser entregue:
| De | Pode ir para |
|---|---|
pending | confirmed, cancelled |
confirmed | shipped, cancelled |
shipped | delivered, cancelled |
delivered | nada (final) |
cancelled | nada (final) |
Pular uma etapa (confirmed → delivered) responde 409 invalid_transition, com from e to no corpo. Enviar o status que o pedido já tem não muda nada.
- Cancelar devolve o estoque de um pedido
pendingouconfirmed, na hora (o da variação, quando o item tem uma). Um pedidoshippedcancelado não devolve: as unidades já saíram da loja. - Pedido da loja conectada. Um pedido que está na sua Shopify ou WooCommerce muda de status lá, não no Vamo:
409 order_managed_by_store(o corpo trazplatform). As observações continuam editáveis. - Pedido esperando aprovação. Um pedido da IA marcado para revisão só muda de status depois que a equipe aprova ou recusa:
409 order_in_review.
Erros
Os erros vêm no formato de sempre: { "error": { "code": "…", "message": "…" } }, com os detalhes ao lado.
| Status | code | Quando |
|---|---|---|
400 | validation_error | Falta storeId, contactId ou items; item sem productName, quantity ou unitPrice; quantidade ou preço que não é inteiro; ID que não é UUID; variantId sem productId; mais de 200 itens; status fora da lista ou PATCH sem nenhum campo |
400 | invalid_idempotency_key | Idempotency-Key com mais de 200 caracteres |
400 | product_not_found | O productId não é um produto dessa loja |
400 | inactive_product | O produto não está ativo |
400 | variant_required | O produto tem variações e o item não diz qual |
400 | variant_not_found | O variantId não é variação desse produto |
400 | mixed_currency | Produtos de moedas diferentes, ou currency diferente da dos produtos |
400 | total_too_large | O total passa do valor máximo |
404 | not_found | Contato, loja, conversa ou pedido não encontrado na sua organização |
409 | out_of_stock | Falta estoque. O corpo traz productName e, quando o Vamo sabe, available |
409 | invalid_transition | O novo status pula uma etapa ou sai de um status final |
409 | order_managed_by_store | O pedido é da loja conectada |
409 | order_in_review | O pedido espera a aprovação da equipe |
{
"error": {
"code": "out_of_stock",
"message": "Not enough stock for \"iPhone 15 (128 GB Azul)\"",
"productName": "iPhone 15 (128 GB Azul)",
"available": 0
}
}