Cancelar orden (partners)
curl --request POST \
--url https://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"reason": "<string>",
"cancellationType": "<string>",
"cancellationNote": "<string>",
"cancellationGroup": "<string>"
}
'import requests
url = "https://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel"
payload = {
"reason": "<string>",
"cancellationType": "<string>",
"cancellationNote": "<string>",
"cancellationGroup": "<string>"
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
reason: '<string>',
cancellationType: '<string>',
cancellationNote: '<string>',
cancellationGroup: '<string>'
})
};
fetch('https://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel', 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://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel",
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>',
'cancellationType' => '<string>',
'cancellationNote' => '<string>',
'cancellationGroup' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);
$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://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel"
payload := strings.NewReader("{\n \"reason\": \"<string>\",\n \"cancellationType\": \"<string>\",\n \"cancellationNote\": \"<string>\",\n \"cancellationGroup\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
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://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"<string>\",\n \"cancellationType\": \"<string>\",\n \"cancellationNote\": \"<string>\",\n \"cancellationGroup\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"<string>\",\n \"cancellationType\": \"<string>\",\n \"cancellationNote\": \"<string>\",\n \"cancellationGroup\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"message": "<string>",
"data.reasonDetail": "<string>",
"data.resolvedFrom": {}
}APIs de partner
Cancelar orden (partners)
Cancela una orden inyectada, por su id externo. Corre la política de cancelación.
POST
/
api
/
v1
/
adapters
/
xmart
/
stores
/
orders
/
{orderId}
/
cancel
Cancelar orden (partners)
curl --request POST \
--url https://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"reason": "<string>",
"cancellationType": "<string>",
"cancellationNote": "<string>",
"cancellationGroup": "<string>"
}
'import requests
url = "https://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel"
payload = {
"reason": "<string>",
"cancellationType": "<string>",
"cancellationNote": "<string>",
"cancellationGroup": "<string>"
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({
reason: '<string>',
cancellationType: '<string>',
cancellationNote: '<string>',
cancellationGroup: '<string>'
})
};
fetch('https://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel', 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://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel",
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>',
'cancellationType' => '<string>',
'cancellationNote' => '<string>',
'cancellationGroup' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);
$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://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel"
payload := strings.NewReader("{\n \"reason\": \"<string>\",\n \"cancellationType\": \"<string>\",\n \"cancellationNote\": \"<string>\",\n \"cancellationGroup\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
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://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"<string>\",\n \"cancellationType\": \"<string>\",\n \"cancellationNote\": \"<string>\",\n \"cancellationGroup\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.fire.rest/api/v1/adapters/xmart/stores/orders/{orderId}/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"<string>\",\n \"cancellationType\": \"<string>\",\n \"cancellationNote\": \"<string>\",\n \"cancellationGroup\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"message": "<string>",
"data.reasonDetail": "<string>",
"data.resolvedFrom": {}
}Cancela una orden que inyectaste, buscándola por el id externo que vos le pusiste. A
diferencia del endpoint de backoffice, no necesitás guardar nuestro UUID interno.
Fire resuelve solo cuál de los dos casos aplica, por la configuración de esa cuenta, país y
vendor. No tenés que averiguarlo: si te corresponde la nota de crédito, el
Este endpoint corre la política de cancelación: las reglas de Fire más las que haya
configurado la cuenta. Antes de intentarlo podés preguntar con Elegibilidad de
cancelación, que devuelve el mismo veredicto y
los mismos
code con un 200 y sin efectos.El orden de los pasos depende del gateway fiscal
Es la parte que más se equivoca al integrar, y la única donde el orden importa.- Con numeración por gateway
- Sin numeración por gateway
El comprobante lo numera Fire, así que la anulación fiscal va primero:Es el mismo patrón que la emisión —primero el hecho fiscal, después la orden—, y por eso
es fácil de recordar: se anula igual que se emite.Si invertís los pasos, este endpoint responde
1
Anular el comprobante
POST /api/v2/external/fiscal/numbering con operation: "CANCEL". Devuelve la nota
de crédito. Ver Numeración fiscal v2.2
Cancelar la orden
Recién ahora, este endpoint.
409 con
FISCAL_REPRESENTATION_NOT_VOIDED. No es transitorio: reintentar no lo arregla.No hay anulación previa que pedir: se cancela directo, con este endpoint y nada más.
409 te lo
dice.
string
requerido
Bearer <api-key> con scope orders:write, acotada a un vendor.string
predeterminado:"es"
Idioma del motivo de un rechazo: Solo afecta a las reglas propias de Fire, que traen etiquetas en los tres idiomas. El
texto de una regla que configuró la cuenta vuelve tal cual la cuenta lo escribió, en el
idioma en que esté escrito. Sin este parámetro, español.
es, en o pt. Es el mismo parámetro que ya usan
Elegibilidad y
Numeración fiscal.Va en la URL:POST https://app.fire.rest/api/v1/adapters/xmart/stores/orders/ORD-123/cancel?locale=pt
string
requerido
El id externo de la orden — el mismo
orderId que mandaste al inyectarla. No es
nuestro UUID interno: no necesitás guardarlo.string
requerido
El motivo. Entre 5 y 500 caracteres. Con catálogo, el texto de la razón elegida.
string
El id del motivo dentro del catálogo. Para canales de agregador tiene que salir del
catálogo SAG.
string
Nota libre, hasta 500 caracteres. Se guarda aparte del motivo.
string
El grupo. No hace falta mandarlo: lo deriva el backend.
Qué trae un rechazo
Además delcode, el cuerpo de un 409 trae el motivo listo para mostrar:
string
El titular: el nombre de la regla que denegó. Es lo que entra en un aviso corto.
string
El porqué, largo. Sólo viene si la regla lo tiene cargado. Va aparte del
message para que
puedas mostrar sólo el titular cuando no hay lugar para más.El número que causó el rechazo, cuando la regla compara uno: el límite y el valor real.
Sirve para decir «se pasó por 17 minutos» sin tener que interpretar el texto.
object
Con qué datos se decidió. Es el recibo para diagnosticar, no para mostrarle a una persona.
Códigos de rechazo
Todos salen con409. Ramificá por code, nunca por el mensaje: el texto es para
mostrarle a una persona y puede cambiar o traducirse sin aviso.
code | Qué pasó | Qué hacer |
|---|---|---|
CANCELLATION_IN_PROGRESS | Ya hay una cancelación disparada. | Esperar; no reintentar en bucle. |
FISCAL_ALREADY_CANCELLED | El documento fiscal ya está anulado. | Nada: el efecto deseado ya ocurrió. |
ORDER_NOT_CANCELLABLE | La orden ya está cerrada o cancelada. | Nada: es estado terminal. |
FISCAL_REPRESENTATION_NOT_VOIDED | Hay factura y todavía no hay nota de crédito. | Pedir primero la anulación fiscal, esperar la respuesta, y recién ahí cancelar. |
BUSINESS_DAY_CLOSED | La orden es de un día de negocio ya cerrado, o anterior al activo. | No se cancela por API: corresponde un ajuste contable. |
CANCELLATION_POLICY_DENIED | Lo negó una regla que configuró la cuenta. | Leer message: el motivo lo escribió el cliente. |
Un
200 significa que la orden quedó cancelada. No significa que el documento
fiscal ya esté anulado: con gateway eso lo hiciste vos en el paso previo, y con emisión
nativa se resuelve después, por el callback del proveedor.
