Registrar venda perdida
curl --request POST \
--url https://api.fire.rest/api/v1/fire/external/orders/lost-sales \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--data '
{
"reason": "<string>",
"detail": {},
"orderId": "<string>",
"store.code": "<string>"
}
'import requests
url = "https://api.fire.rest/api/v1/fire/external/orders/lost-sales"
payload = {
"reason": "<string>",
"detail": {},
"orderId": "<string>",
"store.code": "<string>"
}
headers = {
"x-api-key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({reason: '<string>', detail: {}, orderId: '<string>', 'store.code': '<string>'})
};
fetch('https://api.fire.rest/api/v1/fire/external/orders/lost-sales', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fire.rest/api/v1/fire/external/orders/lost-sales",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'reason' => '<string>',
'detail' => [
],
'orderId' => '<string>',
'store.code' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.fire.rest/api/v1/fire/external/orders/lost-sales"
payload := strings.NewReader("{\n \"reason\": \"<string>\",\n \"detail\": {},\n \"orderId\": \"<string>\",\n \"store.code\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.fire.rest/api/v1/fire/external/orders/lost-sales")
.header("x-api-key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"<string>\",\n \"detail\": {},\n \"orderId\": \"<string>\",\n \"store.code\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fire.rest/api/v1/fire/external/orders/lost-sales")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"<string>\",\n \"detail\": {},\n \"orderId\": \"<string>\",\n \"store.code\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyAPI
Registrar venda perdida
Avisa que você cobrou uma venda no caixa e ela nunca chegou a virar pedido na Fire.
POST
/
api
/
v1
/
fire
/
external
/
orders
/
lost-sales
Registrar venda perdida
curl --request POST \
--url https://api.fire.rest/api/v1/fire/external/orders/lost-sales \
--header 'Content-Type: application/json' \
--header 'x-api-key: <x-api-key>' \
--data '
{
"reason": "<string>",
"detail": {},
"orderId": "<string>",
"store.code": "<string>"
}
'import requests
url = "https://api.fire.rest/api/v1/fire/external/orders/lost-sales"
payload = {
"reason": "<string>",
"detail": {},
"orderId": "<string>",
"store.code": "<string>"
}
headers = {
"x-api-key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({reason: '<string>', detail: {}, orderId: '<string>', 'store.code': '<string>'})
};
fetch('https://api.fire.rest/api/v1/fire/external/orders/lost-sales', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fire.rest/api/v1/fire/external/orders/lost-sales",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'reason' => '<string>',
'detail' => [
],
'orderId' => '<string>',
'store.code' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.fire.rest/api/v1/fire/external/orders/lost-sales"
payload := strings.NewReader("{\n \"reason\": \"<string>\",\n \"detail\": {},\n \"orderId\": \"<string>\",\n \"store.code\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.fire.rest/api/v1/fire/external/orders/lost-sales")
.header("x-api-key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"<string>\",\n \"detail\": {},\n \"orderId\": \"<string>\",\n \"store.code\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fire.rest/api/v1/fire/external/orders/lost-sales")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"<string>\",\n \"detail\": {},\n \"orderId\": \"<string>\",\n \"store.code\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyUma venda perdida é dinheiro que se movimentou no balcão e não ficou registrado como venda. O
caixa cobrou, algo impediu que o pedido fosse criado, e você devolveu o valor ali mesmo.
Todo o resto do payload —
Não leva header
Sem esta chamada, essa venda não existe em lugar nenhum. Não há pedido, não há evento e
—dependendo da causa— também não fica registro no domínio que falhou. O fechamento de caixa não
consegue explicar e ninguém fica sabendo que uma loja parou de vender.
Não é um cancelamento. Um cancelamento tem pedido, nota de crédito e evento
order.reversed.
Aqui a venda nunca chegou a existir.Não é você quem decide reportar. A Fire decide e avisa em
policy.numberingFailure.action de Emitir comprovante:
REFUND significa devolver a cobrança e reportar aqui; CONTINUE, seguir normal e não
reportar nada. A regra é definida pela conta por vendor, então pode ser diferente entre duas
lojas do mesmo cliente — por isso é perguntada em cada venda e nunca fica em cache.O corpo é o da injeção
Não monte um payload novo. Mande exatamente o mesmo JSON que você ia mandar para Criar pedido, e acrescente duas chaves no mesmo nível:reason e
detail.
Não é conveniência: por dentro roda o mesmo mapeamento da injeção, então a venda perdida fica
guardada com a mesma forma de uma vendida — mesmas linhas, mesmos totais, mesmos meios de pagamento.
É isso que depois permite fechar o caixa do dia somando as duas.
string
obrigatório
Por que a venda não virou pedido.
Não deduza: devolvemos em
| valor | quando |
|---|---|
FISCAL_NUMBERING_FAILED | Você pediu a numeração com Emitir comprovante e falhou |
policy.numberingFailure.lostSaleReason da resposta da numeração.
Copie. No dia em que adicionarmos uma causa, você não mexe em nada.É um enum fechado e não há endpoint para consultá-lo: a tabela acima é o catálogo completo,
e o valor de que você precisa já veio na resposta que te trouxe até aqui. Enquanto for deste
tamanho, uma chamada a mais para descobri-lo não compra nada. Se crescer, vira um endpoint e
você vai ver isso anunciado aqui — o campo não muda.Qualquer outro valor volta 400.object
O que a causa carrega. Para
Opcional de propósito: o pior caso —um erro de configuração, que corta antes de criar a
solicitação fiscal— não tem nada disso, e exigir deixaria de fora justamente o caso mais difícil
de detectar.
FISCAL_NUMBERING_FAILED copie da resposta da numeração:| da resposta do prekey | para detail |
|---|---|
failure.code | detail.code |
failure.message | detail.message |
fiscalRequestId | detail.fiscalRequestId |
failure (inteiro) | detail.failure |
policy.numberingFailure (inteiro) | detail.policy |
string
obrigatório
Do payload de injeção. Junto com o vendor é a chave que torna o reenvio seguro.
string
obrigatório
Do payload de injeção. Sem ela não dá para fechar o caixa nem saber quem parou de vender.
client, order.products, payments, createdAt, orderCode…— viaja
tal como está e é interpretado com o mesmo mapeamento de sempre.
Autenticação
string
obrigatório
Sua API key da Fire com escopo
orders:write. A key precisa ser vendor-scoped — keys sem
vendorId são rejeitadas com 403.Reenviar é seguro
É idempotente pororderId + vendor, a mesma chave com que a Fire identifica um pedido. Se o
caixa ficar sem rede bem aqui —um momento ruim, com o cliente na frente— acumule e reenvie.
| resposta | o que aconteceu |
|---|---|
201 | Registrada agora |
200 | Já estava registrada. Seu reenvio chegou bem e nada foi duplicado |
Idempotency-Key: não existem duas perdas diferentes da mesma venda.
Exemplo
Request
{
"reason": "FISCAL_NUMBERING_FAILED",
"detail": {
"code": "FISCAL_BUSINESS_RULE",
"message": "identidad fiscal no configurada: EC / la tienda K000 no tiene el punto de emisión \"8cd0b157\"",
"fiscalRequestId": "fr_01HZ8N4K2P",
"failure": { "code": "FISCAL_BUSINESS_RULE", "scope": "FUNCTIONAL" },
"policy": {
"action": "REFUND",
"lostSaleReason": "FISCAL_NUMBERING_FAILED",
"configVersion": "fnv1a:d096701f",
"resolvedFrom": { "retryable": "false", "operation": "INVOICE" }
}
},
"orderId": "EC-K000-POS-1-1787239618530373",
"orderCode": "EC-K000-POS-1-1787239618530373",
"createdAt": "2026-08-21T14:32:09.881Z",
"accountId": 51,
"account": "KFC Kioscos EC",
"selectedShippingMethod": "pickup",
"client": { "uid": "c-1", "name": "Consumidor", "lastName": "Final" },
"store": { "id": 1, "code": "K000", "vendorId": "51.1.10" },
"order": { "products": [ "…suas linhas, tal como estão…" ] },
"payments": { "totals": [ "…" ], "paymentMethods": [ "…" ] }
}
201
{
"success": true,
"data": { "id": "3f2a8c11-9d54-4b7e-8f11-2c9b0e7a4d63", "alreadyRecorded": false }
}
Erros
| código | quando |
|---|---|
400 | Falta reason, orderId ou store.code — ou reason traz um valor que não está na tabela |
401 | API key ausente ou inválida |
403 | A key não tem escopo orders:write, ou não é vendor-scoped |
404 | A loja não existe sob o vendor da sua key |
Um campo a mais não é rejeitado, e um dia de negócio fechado também não: o dinheiro já se
moveu, e esse mesmo dia fechado pode ser a causa da próxima perda. Preferimos guardar demais a
perder o rastro de uma venda.

