• Documentación

    • Información general
    • Entornos
    • Primeros pasos
    • Listar CFDI's
    • Buscar CFDI
    • Crear CFDI 4.0
    • Crear CFDI Global 4.0
    • Borradores CFDI 4.0
    • Descargar CFDI
    • Cancelar CFDI 4.0
    • Descargar acuse CFDI 4.0
    • Enviar CFDI
    • Consultar estatus de cancelación de un CFDI
    • Autofacturación
    • Grupos de empleados
    • Empleados
    • Nóminas
    • Complementos
    • Retenciones
    • Complementos de retenciones
    • Carta porte v3.1
    • Catálogos
    • Clientes
    • Empresas
    • Migraciones
    • Series
    • Productos
    • Addendas
    • Fundamentos legales del SAT

Autofacturación

Introducción

El módulo de autofacturación es una función que permite cargar facturas a nuestro sistema con información específica como la de un ticket de venta, en este módulo sus clientes pueden acceder al link de autofacturación y por medio de un ID, la fecha de venta y total del ticket pueden generar ellos mismos su propia factura ya sea por consumo en un restaurante o alguna venta de mostrador.

Tip

El módulo de autofacturación no está incluido en todos los planes de Factu-Ramval si quieres conocer más detalles de los planes que lo incluyen o sobre su funcionamiento puedes seguir el siguiente link

Autofacturación Factu-Ramval

El panel de autofacturación se configura a través de la interfaz y el uso del API es para administrar las facturas que de nuestro módulo.

A continuación veremos como cargar órdenes al módulo, para eso existen dos endpoints distintos:

El endpoint de múltiples órdenes, que acepta un arreglo de objetos, permitiendo enviar varias órdenes en una sola solicitud.

El endpoint de una orden, que recibe únicamente un objeto por petición.

Cargar múltiples órdenes

Te explicamos como cargar múltiples a continuación.

 Parametro Tipo Requerido Detallles
 vencimiento String Requerido

 Se utiliza para indicar la fecha limite que tendra el cliente para timbrar su factura.

Este campo debe ingresarse con el siguiente formato:

"2025-03-14"

 folio Numerico Requerido

 Indica el folio por el cual identificaremos la orden este puede ser personalizado pero no debe repetirse con otras ordenes ya que no permitira ingresarlo.

Ejemplo: 01

 importe Numerico Requerido

 Indica la cantidad de dinero correspondiente de la orden aqui podemos definir el total del ticket.

Ejemplo: 123.45

NOTA: Esta cantidad siempre incluye el IVA y se calcula con el porcentaje que ingresamos en el campo 'iva'

Es decir 'importe' => 123.45    'iva' => 16

Subtotal = 106.42

Total = 17.03

 fecha String Requerido

 Se utiliza para definir la fecha en la que se realizo la venta o que generamos el ticket para nuestros clientes

Este campo debe ingresarse con el siguiente formato:

"2025-03-31"

 iva Numerico Requerido

 Con este campo podemos definir la tasa de IVA utilizado en la venta que se aplicara a el importe de la orden

Admite los siguientes valores:

16
8
4
0
exento

NOTA: Los porcentajes estan disponibles de acuerdo a los estimulos fiscales a los que corresponde nuestro RFC, puede ser posible que no aplique alguno de los porcentajes para ti, esto debes revisarlo con tu contador antes de implementarlos.

 formaDePago String Opcional

 Aquí podemos editar la forma de pago que tuvo la orden, utilizando las claves del SAT para las Formas de pago .

Ejemplo:

"01" (Efectivo)

 ish Numerico Opcional

 Esta campo es para especificar la tasa correspondiente al Impuesto Sobre el Hospedaje (ISH), aplicable a clientes del sector hotelero.

Ejemplo:

"5" = 5%

 tag String Opcional

 Se puede usar para agregar una etiqueta personalizada a la orden, lo que permite clasificarla o identificar su origen, ademas, se podra usar este elemento para configuraciones en el autofacturador.

Ejemplo:

Puede usar los tags "ONLINE" y "TIENDA" para distinguir si la orden proviene de la tienda en línea o de una sucursal física.

 objetoImpuesto String Opcional

 Se puede utilizar para definir el tipo de impuesto que aplica al concepto facturado. Si no se envía, se asignará por defecto la clave 02

Opciones:
"01": No objeto de impuesto.
"02": Si objeto de impuesto.
"03": Si objeto de impuesto y no obligado al desglose
"04": Si objeto de impuesto y no causa impuesto
"05": Si objeto del impuesto, IVA crédito PODEBI

Nota: Este campo tiene prioridad sobre otros impuestos. Si se envía con las claves 01, 03, 04 o 05, el sistema ignorará cualquier impuesto especificado en la petición, incluso si se incluyen.

Tip

Importante el metodo para cargar multiples ordenes es de tipo POST

Construcción de la URL

Host: https://app.facturamval.com/api (producción) / https://sandbox.facturamval.com/api (sandbox)

Endpoint: /v4/autofacturacion/multiple

Ejemplo: https://app.facturamval.com/api/v4/autofacturacion/multiple

Ejemplo para cargar múltiples órdenes al modulo de autofacturación

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => '{ HOST }/v4/autofacturacion/multiple',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS =>'[
    {
        "vencimiento": "2025-03-31",
        "folio": "55101",
        "importe": 100.00,
        "fecha": "2025-03-25",
        "iva": "16",
        "formaDePago": "03",
        "tag":"",
        "objetoImpuesto": "02"
    },
    {
        "vencimiento": "2025-03-31",
        "folio": "55102",
        "importe": 200.00,
        "fecha": "2025-03-25",
        "iva": "0",
        "formaDePago": "01",
        "ish": 5,
        "tag":"HOTEL",
        "objetoImpuesto": "01"
    },
    {
        "vencimiento": "2025-03-31",
        "folio": "55103",
        "importe": 280.00,
        "fecha": "2025-03-26",
        "iva": "16",
        "formaDePago": "28",
        "ish": 0,
        "tag":"",
        "objetoImpuesto": "01"
    }          
]',
  CURLOPT_HTTPHEADER => array(
    'F-Api-Key: Tu API key',
    'F-Secret-Key: Tu Secret key',
    'Content-Type: application/json'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

var request = require('request');
var options = {
  'method': 'POST',
  'url': '{ HOST }/v4/autofacturacion/multiple',
  'headers': {
    'F-Api-Key': 'Tu API key',
    'F-Secret-Key': 'Tu Secret key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify([
    {
      "vencimiento": "2025-03-31",
      "folio": "55101",
      "importe": 100,
      "fecha": "2025-03-25",
      "iva": "16",
      "formaDePago": "03",
      "tag": "",
      "objetoImpuesto": "02"
    },
    {
      "vencimiento": "2025-03-31",
      "folio": "55102",
      "importe": 200,
      "fecha": "2025-03-25",
      "iva": "0",
      "formaDePago": "01",
      "ish": 5,
      "tag": "HOTEL",
      "objetoImpuesto": "01"
    },
    {
      "vencimiento": "2025-03-31",
      "folio": "55103",
      "importe": 280,
      "fecha": "2025-03-26",
      "iva": "16",
      "formaDePago": "28",
      "ish": 0,
      "tag": "",
      "objetoImpuesto": "01"
    }
  ])

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

import requests
import json

url = "{ HOST }/v4/autofacturacion/multiple"

payload = json.dumps([
  {
    "vencimiento": "2025-03-31",
    "folio": "55101",
    "importe": 100,
    "fecha": "2025-03-25",
    "iva": "16",
    "formaDePago": "03",
    "tag": "",
    "objetoImpuesto": "02"
  },
  {
    "vencimiento": "2025-03-31",
    "folio": "55102",
    "importe": 200,
    "fecha": "2025-03-25",
    "iva": "0",
    "formaDePago": "01",
    "ish": 5,
    "tag": "HOTEL",
    "objetoImpuesto": "01"
  },
  {
    "vencimiento": "2025-03-31",
    "folio": "55103",
    "importe": 280,
    "fecha": "2025-03-26",
    "iva": "16",
    "formaDePago": "28",
    "ish": 0,
    "tag": "",
    "objetoImpuesto": "01"
  }
])
headers = {
  'F-Api-Key': 'Tu API key',
  'F-Secret-Key': 'Tu Secret key',
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

require "uri"
require "json"
require "net/http"

url = URI("{ HOST }/v4/autofacturacion/multiple")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["F-Api-Key"] = "Tu API key"
request["F-Secret-Key"] = "Tu Secret key"
request["Content-Type"] = "application/json"
request.body = JSON.dump([
  {
    "vencimiento": "2025-03-31",
    "folio": "55101",
    "importe": 100,
    "fecha": "2025-03-25",
    "iva": "16",
    "formaDePago": "03",
    "tag": "",
    "objetoImpuesto": "02"
  },
  {
    "vencimiento": "2025-03-31",
    "folio": "55102",
    "importe": 200,
    "fecha": "2025-03-25",
    "iva": "0",
    "formaDePago": "01",
    "ish": 5,
    "tag": "HOTEL",
    "objetoImpuesto": "01"
  },
  {
    "vencimiento": "2025-03-31",
    "folio": "55103",
    "importe": 280,
    "fecha": "2025-03-26",
    "iva": "16",
    "formaDePago": "28",
    "ish": 0,
    "tag": "",
    "objetoImpuesto": "01"
  }
])

response = http.request(request)
puts response.read_body

Respuestas al crear múltiples órdenes

Respuesta Exitosa

{
    "response": "success",
    "message": "Registros creados",
    "data": [
        {
            "soft_folio": "55101",
            "soft_fecha": "2025-03-25",
            "soft_importe": "100",
            "soft_creado": "2025-03-27",
            "soft_facturado": 0,
            "due_date": "2025-03-31",
            "soft_tasa": "16",
            "soft_forma_de_pago": "03",
            "soft_ish": 0,
            "soft_id": 2958927
        },
        {
            "soft_folio": "55102",
            "soft_fecha": "2025-03-25",
            "soft_importe": "200",
            "soft_creado": "2025-03-27",
            "soft_facturado": 0,
            "due_date": "2025-03-31",
            "soft_tasa": "Obj_01",
            "soft_forma_de_pago": "01",
            "soft_ish": "5",
            "soft_id": 2958928
        },
        {
            "soft_folio": "55103",
            "soft_fecha": "2025-03-26",
            "soft_importe": "280",
            "soft_creado": "2025-03-27",
            "soft_facturado": 0,
            "due_date": "2025-03-31",
            "soft_tasa": "Obj_01",
            "soft_forma_de_pago": "28",
            "soft_ish": "0",
            "soft_id": 2958929
        }
    ],
    "folios_existentes": []
}

Respuesta erronea cuando la orden ya existe

{
    "response": "success",
    "message": "Registros creados",
    "data": [],
    "folios_existentes": [
        {
            "soft_id": 2958927,
            "soft_folio": "55101",
            "soft_fecha": "2025-03-25",
            "soft_importe": "100.00",
            "soft_creado": "2025-03-27",
            "soft_facturado": 0,
            "soft_cfdi_uuid": "",
            "is_deleted": "0",
            "due_date": "2025-03-31",
            "soft_tasa": "16",
            "soft_forma_de_pago": "03",
            "soft_ish": "0",
            "soft_cfdi_date": null
        },
        {
            "soft_id": 2958928,
            "soft_folio": "55102",
            "soft_fecha": "2025-03-25",
            "soft_importe": "200.00",
            "soft_creado": "2025-03-27",
            "soft_facturado": 0,
            "soft_cfdi_uuid": "",
            "is_deleted": "0",
            "due_date": "2025-03-31",
            "soft_tasa": "Obj_01",
            "soft_forma_de_pago": "01",
            "soft_ish": "5",
            "soft_cfdi_date": null
        }
    ]
}

Respuesta erronea cuando hace falta información

En esta respuesta, podemos ver que se hace referencia a la orden que tiene el error, agregando el número en el orden de carga, comenzando desde 0 en adelante, en ejemplo viene el número "0.fecha", significando que el primer registro es el que tiene el error.

{
    "response": "error",
    "message": {
        "0.fecha": [
            "El campo 0.fecha es requerido"
        ]
    }
}

Aviso

El mensaje de error puede variar dependiendo el nodo en el que haya información incorrecta. Te sugerimos leer cuidadosamente el mensaje del error ya que en el mismo se indica donde es necesario corregir la información.

Cargar una orden

Ahora, así podemos cargar una sola orden a nuestro módulo de autofacturación.

 Parametro Tipo Requerido Detallles
 vencimiento String Requerido

 Se utiliza para indicar la fecha limite que tendra el cliente para timbrar su factura

Este campo debe ingresarse con el siguiente formato:

"2023-09-28"

 folio Numerico Requerido

 Indica el folio por el cual identificaremos la orden este puede ser personalizado pero no debe repetirse con otras ordenes ya que no permitira ingresarlo

Ejemplo: 01

 importe Numerico Requerido

 Indica la cantidad de dinero correspondiente de la orden aqui podemos definir el total del ticket

Ejemplo: 123.45

NOTA: Esta cantidad siempre incluye el IVA y se calcula con el porcentaje que ingresamos en el campo 'iva'

Es decir 'importe' => 123.45    'iva' => 16

Subtotal = 106.42

Total = 17.03

 fecha String Requerido

 Se utiliza para definir la fecha en la que se realizo la venta o que generamos el ticket para nuestros clientes

Este campo debe ingresarse con el siguiente formato:

"2023-08-28"

 iva Numerico Requerido

 Con este campo podemos definir la tasa de IVA utilizado en la venta que se aplicara a el importe de la orden

Admite los siguientes valores:

16
8
4
0
exento

NOTA: Los porcentajes estan disponibles de acuerdo a los estimulos fiscales a los que corresponde nuestro RFC, puede ser posible que no aplique alguno de los porcentajes para ti, esto debes revisarlo con tu contador antes de implementarlos.

 formaDePago String Opcional

 Aquí podemos editar la forma de pago que tuvo la orden, utilizando las claves del SAT para las Formas de pago .

Ejemplo:

"01" (Efectivo)

 ish Numerico Opcional

 Esta campo es para especificar la tasa correspondiente al Impuesto Sobre el Hospedaje (ISH), aplicable a clientes del sector hotelero.

Ejemplo:

"5" = 5%

 tag String Opcional

 Se puede usar para agregar una etiqueta personalizada a la orden, lo que permite clasificarla o identificar su origen, ademas, se podra usar este elemento para configuraciones en el autofacturador.

Ejemplo:

Puede usar los tags "ONLINE" y "TIENDA" para distinguir si la orden proviene de la tienda en línea o de una sucursal física.

 objetoImpuesto String Opcional

 Se puede utilizar para definir el tipo de impuesto que aplica al concepto facturado. Si no se envía, se asignará por defecto la clave 02

Opciones:
"01": No objeto de impuesto.
"02": Si objeto de impuesto.
"03": Si objeto de impuesto y no obligado al desglose
"04": Si objeto de impuesto y no causa impuesto
"05": Si objeto del impuesto, IVA crédito PODEBI

Nota: Este campo tiene prioridad sobre otros impuestos. Si se envía con las claves 01, 03, 04 o 05, el sistema ignorará cualquier impuesto especificado en la petición, incluso si se incluyen.

Tip

Importante el metodo para cargar una orden es de tipo POST

Construcción de la URL

Host: https://app.facturamval.com/api (producción) / https://sandbox.facturamval.com/api (sandbox)

Endpoint: /v4/autofacturacion/

Ejemplo: https://app.facturamval.com/api/v4/autofacturacion/

Tip

Para probar el código de ejemplo es necesario que reemplaces el texto Tu API key por el API KEY de tu cuenta, e Tu Secret key por el SECRET KEY correspondiente. Así como cambiar los UID de los CFDIs relacionados y de receptor.

Ejemplo para cargar una orden al modulo de autofacturación

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => '{ HOST }/v4/autofacturacion',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS =>'{
        "folio":"55104",
        "importe": "200.00",
        "fecha": "2025-03-14",
        "vencimiento": "2025-03-31",
        "iva": 16,
        "formaDePago": "03",
        "ish": 5,
        "tag": "",
        "objetoImpuesto": "02"
}
',
  CURLOPT_HTTPHEADER => array(
    'F-Api-Key: Tu API key',
    'F-Secret-Key: Tu Secret key',
    'Content-Type: application/json'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

var request = require('request');
var options = {
  'method': 'POST',
  'url': '{ HOST }/v4/autofacturacion',
  'headers': {
    'F-Api-Key': 'Tu API key',
    'F-Secret-Key': 'Tu Secret key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "folio": "55104",
    "importe": "200.00",
    "fecha": "2025-03-14",
    "vencimiento": "2025-03-31",
    "iva": 16,
    "formaDePago": "03",
    "ish": 5,
    "tag": "",
    "objetoImpuesto": "02"
  })

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

import requests
import json

url = "{ HOST }/v4/autofacturacion"

payload = json.dumps({
  "folio": "55104",
  "importe": "200.00",
  "fecha": "2025-03-14",
  "vencimiento": "2025-03-31",
  "iva": 16,
  "formaDePago": "03",
  "ish": 5,
  "tag": "",
  "objetoImpuesto": "02"
})
headers = {
  'F-Api-Key': 'Tu API key',
  'F-Secret-Key': 'Tu Secret key',
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

require "uri"
require "json"
require "net/http"

url = URI("{ HOST }/v4/autofacturacion")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["F-Api-Key"] = "Tu API key"
request["F-Secret-Key"] = "Tu Secret key"
request["Content-Type"] = "application/json"
request.body = JSON.dump({
  "folio": "55104",
  "importe": "200.00",
  "fecha": "2025-03-14",
  "vencimiento": "2025-03-31",
  "iva": 16,
  "formaDePago": "03",
  "ish": 5,
  "tag": "",
  "objetoImpuesto": "02"
})

response = http.request(request)
puts response.read_body

Respuestas al crear una orden

Respuesta Exitosa

{
    "response": "success",
    "message": "Registro creado",
    "data": {
        "soft_folio": "55104",
        "soft_fecha": "2025-03-14",
        "soft_importe": "200.00",
        "soft_creado": "2025-03-27",
        "soft_facturado": 0,
        "due_date": "2025-03-31",
        "soft_tasa": "16",
        "soft_forma_de_pago": "03",
        "soft_ish": "5",
        "soft_id": 2958930
    }
}

Respuesta erronea cuando la orden ya existe

{
    "response": "error",
    "message": "El registro ya existe",
    "data": {
        "soft_id": 499,
        "soft_folio": 99,
        "soft_fecha": "2023-08-28",
        "soft_importe": "240.00",
        "soft_creado": "2023-08-29",
        "soft_facturado": 0,
        "soft_account_id": 1464,
        "soft_cfdi_uuid": "",
        "is_deleted": "0",
        "due_date": "2023-09-28",
        "soft_tasa": "16"
    }
}

Respuesta erronea cuando hace falta información

{
    "response": "error",
    "message": {
        "folio": [
            "El campo folio es requerido"
        ]
    }
}

Aviso

El mensaje de error puede variar dependiendo el nodo en el que haya información incorrecta. Te sugerimos leer cuidadosamente el mensaje del error ya que en el mismo se indica donde es necesario corregir la información.

Listar ordenes

A continuación se explica como funciona el método con el cual podras listar todas las ordenes de tu modulo de autofacturación.

Podemos listar las ordenes en nuestro modulo haciendo uso de los siguientes parámetros:

 Parametro Tipo Requerido Detallles
 page Numerico Opcional

 Se utiliza para navegar en el paginado de las ordenes de nuestro autofacturador, con el indicamos cual pagina de las disponibles en nuestro listado queremos visualizar.

Ejemplo: 1
 per_page Numerico Opcional

 Indica el numero de registros por pagina que recuperamos al consultar las ordenes en nuestro autofacturador.

Por defecto el maximo de ordenes que podemos visualizar son 100 por pagina

Ejemplo: 40

 fecha String Opcional

 Se utiliza para obtener las ordenes de un dia en especifico.

Es importante tomar en cuenta que esta fecha hace referencia a la fecha que se realizo la venta original, en la respuesta podemos observar  3 fechas:

'vencimiento' - Es el ultimo dia que tienen para generar la factura
'fecha' - El dia que se genero la venta de esta orden
'creado' - Registra el dia que cargamos la orden

Al enviar este campo nos referimos a 'fecha'

Este campo debe ingresarse con el siguiente formato:

"2023-08-28"

Tip

Importante el metodo para listar ordenes es de tipo GET

Construcción de la URL

Host: https://app.facturamval.com/api (producción) / https://sandbox.facturamval.com/api (sandbox)

Endpoint: /v4/autofacturacion/

Ejemplo: https://app.facturamval.com/api/v4/autofacturacion/

Tip

Para probar el código de ejemplo es necesario que reemplaces el texto Tu API key por el API KEY de tu cuenta, e Tu Secret key por el SECRET KEY correspondiente. Así como cambiar los UID de los CFDIs relacionados y de receptor.

Ejemplo para listar todas las ordenes de nuestro módulo

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => '{ HOST }/v4/autofacturacion',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_POSTFIELDS =>'{
    "page": 1,
    "per_page": 40,
    "fecha": "2023-08-28"
}
',
  CURLOPT_HTTPHEADER => array(
    'F-Api-Key: Tu API key',
    'F-Secret-Key: Tu Secret key',
    'Content-Type: application/json'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

var request = require('request');
var options = {
  'method': 'GET',
  'url': '{ HOST }/v4/autofacturacion',
  'headers': {
    'F-Api-Key': 'Tu API key',
    'F-Secret-Key': 'Tu Secret key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "page": 1,
    "per_page": 40,
    "fecha": "2023-08-28"
  })

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

import requests
import json

url = "{ HOST }/v4/autofacturacion"

payload = json.dumps({
  "page": 1,
  "per_page": 40,
  "fecha": "2023-08-28"
})
headers = {
  'F-Api-Key': 'Tu API key',
  'F-Secret-Key': 'Tu Secret key',
  'Content-Type': 'application/json'
}

response = requests.request("GET", url, headers=headers, data=payload)

print(response.text)

require "uri"
require "json"
require "net/http"

url = URI("{ HOST }/v4/autofacturacion")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Get.new(url)
request["F-Api-Key"] = "Tu API key"
request["F-Secret-Key"] = "Tu Secret key"
request["Content-Type"] = "application/json"
request.body = JSON.dump({
  "page": 1,
  "per_page": 40,
  "fecha": "2023-08-28"
})

response = http.request(request)
puts response.read_body

Respuestas al listar las ordenes

Respuesta Exitosa

{
    "response": "success",
    "page": "1",
    "per_page": "100",
    "data": [
        {
            "id": 498,
            "vencimiento": "2023-09-28",
            "folio": 98,
            "importe": "240.00",
            "uuid": "",
            "fecha": "2023-08-28",
            "creado": "2023-08-29",
            "facturado": "no",
            "tasa": "16"
        },
        {
            "id": 499,
            "vencimiento": "2023-09-28",
            "folio": 99,
            "importe": "240.00",
            "uuid": "",
            "fecha": "2023-08-28",
            "creado": "2023-08-29",
            "facturado": "no",
            "tasa": "16"
        },
        {
            "id": 500,
            "vencimiento": "2023-09-28",
            "folio": 100,
            "importe": "240.00",
            "uuid": "",
            "fecha": "2023-08-28",
            "creado": "2023-08-29",
            "facturado": "no",
            "tasa": "16"
        },
        .
        .
        .
        .
    ]
}

Respuesta cuando no existen registros

{
    "response": "success",
    "page": "100",
    "per_page": "40",
    "data": []
}

Respuesta erronea cuando se envia un campo con formato erroneo

{
    "response": "error",
    "message": {
        "fecha": [
            "El campo fecha no corresponde con el formato Y-m-d."
        ]
    }
}

Aviso

El mensaje de error puede variar dependiendo el nodo en el que haya información incorrecta. Te sugerimos leer cuidadosamente el mensaje del error ya que en el mismo se indica donde es necesario corregir la información.

Buscar una orden

A continuación se explica como funciona el método con el cual podras buscar una orden en especifico de tu modulo de autofacturación.

Podemos buscar las ordenes en nuestro modulo haciendo uso de los siguientes parámetros:

 Parametro Tipo Requerido Detallles
 folio Numerico Requerido

Indica el folio que asignamos cuando cargamos la orden a el autofacturador, con este numero podemos identificarlo y acceder a el para consultarlo

Ejemplo: 77

Tip

Importante el metodo para buscar una orden es de tipo GET

Construcción de la URL

Host: https://app.facturamval.com/api (producción) / https://sandbox.facturamval.com/api (sandbox)

Endpoint: /v4/autofacturacion/folio/{ID}

Ejemplo: https://app.facturamval.com/api/v4/autofacturacion/folio/77

Tip

Para probar el código de ejemplo es necesario que reemplaces el texto Tu API key por el API KEY de tu cuenta, e Tu Secret key por el SECRET KEY correspondiente. Así como cambiar los UID de los CFDIs relacionados y de receptor.

Ejemplo para buscar una orden de nuestro módulo

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => '{ HOST }/v4/autofacturacion/folio/77',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => array(
    'F-Api-Key: Tu API key',
    'F-Secret-Key: Tu Secret key'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

var request = require('request');
var options = {
  'method': 'GET',
  'url': '{ HOST }/v4/autofacturacion/folio/77',
  'headers': {
    'F-Api-Key': 'Tu API key',
    'F-Secret-Key': 'Tu Secret key'
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

import requests

url = "{ HOST }/v4/autofacturacion/folio/77"

payload = {}
headers = {
  'F-Api-Key': 'Tu API key',
  'F-Secret-Key': 'Tu Secret key'
}

response = requests.request("GET", url, headers=headers, data=payload)

print(response.text)

require "uri"
require "net/http"

url = URI("{ HOST }/v4/autofacturacion/folio/77")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Get.new(url)
request["F-Api-Key"] = "Tu API key"
request["F-Secret-Key"] = "Tu Secret key"

response = http.request(request)
puts response.read_body

Respuestas al buscar una orden

Respuesta Exitosa

{
    "response": "success",
    "page": 1,
    "per_page": 100,
    "data": {
        "id": 469,
        "vencimiento": "2023-07-05",
        "folio": 77,
        "importe": "1000.00",
        "uuid": "",
        "fecha": "2023-06-05",
        "creado": "2023-06-05",
        "facturado": "no",
        "tasa": "45"
    }
}

Respuesta erronea cuando no se encuentra la orden

{
    "response": "success",
    "page": 1,
    "per_page": 100,
    "data": null
}

Aviso

El mensaje de error puede variar dependiendo el nodo en el que haya información incorrecta. Te sugerimos leer cuidadosamente el mensaje del error ya que en el mismo se indica donde es necesario corregir la información.

Actualizar una orden

A continuación se explica como funciona el método con el cual podras actualizar una orden en especifico de tu modulo de autofacturación.

Podemos actualizar las ordenes en nuestro modulo haciendo uso de los siguientes parámetros:

 Parametro Tipo Requerido Detallles
 vencimiento String Opcional

 Se utiliza para indicar la fecha limite que tendra el cliente para timbrar su factura

Este campo debe ingresarse con el siguiente formato:

"2025-03-31"

 importe Numerico Opcional

 Indica la cantidad de dinero correspondiente de la orden aqui podemos definir el total del ticket

Ejemplo: 123.45

NOTA: Esta cantidad siempre incluye el IVA y se calcula con el porcentaje que ingresamos en el campo 'iva'

Es decir 'importe' => 123.45    'iva' => 16

Subtotal = 106.42

Total = 17.03

 fecha String Opcional

 Se utiliza para definir la fecha en la que se realizo la venta o que generamos el ticket para nuestros clientes

Este campo debe ingresarse con el siguiente formato:

"2025-03-16"

 iva Numerico Opcional

 Con este campo podemos definir la tasa de IVA utilizado en la venta que se aplicara a el importe de la orden

Admite los siguientes valores:

16
8
4
0
exento

NOTA: Los porcentajes estan disponibles de acuerdo a los estimulos fiscales a los que corresponde nuestro RFC, puede ser posible que no aplique alguno de los porcentajes para ti, esto debes revisarlo con tu contador antes de implementarlos.

 formaDePago String Opcional

 Aquí podemos editar la forma de pago que tuvo la orden, utilizando las claves del SAT para las Formas de pago .

Ejemplo:

"01" (Efectivo)

 ish Numerico Opcional

 Esta campo es para especificar la tasa correspondiente al Impuesto Sobre el Hospedaje (ISH), aplicable a clientes del sector hotelero.

Ejemplo:

"5" = 5%

 tag String Opcional

 Se puede usar para agregar una etiqueta personalizada a la orden, lo que permite clasificarla o identificar su origen, ademas, se podra usar este elemento para configuraciones en el autofacturador.

Ejemplo:

Puede usar los tags "ONLINE" y "TIENDA" para distinguir si la orden proviene de la tienda en línea o de una sucursal física.

 objetoImpuesto String Opcional

 Se puede utilizar para definir el tipo de impuesto que aplica al concepto facturado. Si no se envía, se asignará por defecto la clave 02

Opciones:
"01": No objeto de impuesto.
"02": Si objeto de impuesto.
"03": Si objeto de impuesto y no obligado al desglose
"04": Si objeto de impuesto y no causa impuesto
"05": Si objeto del impuesto, IVA crédito PODEBI

Nota: Este campo tiene prioridad sobre otros impuestos. Si se envía con las claves 01, 03, 04 o 05, el sistema ignorará cualquier impuesto especificado en la petición, incluso si se incluyen.

Tip

Importante el metodo para actualizar una orden es de tipo PATCH

Construcción de la URL

Host: https://app.facturamval.com/api (producción) / https://sandbox.facturamval.com/api (sandbox)

Endpoint para actualizar por folio: /v4/autofacturacion/folio/{FOLIO}

Ejemplo: https://app.facturamval.com/api/v4/autofacturacion/folio/91

Endpoint para actualizar por ID: /v4/autofacturacion/{ID}

Ejemplo: https://app.facturamval.com/api/v4/autofacturacion/2958233

Tip

El FOLIO es el número con el que subiste tu orden o ticket al autofacturador, mientras que, el ID se consigue utilizando el método de listar órdenes.

Ejemplo para actualizar una orden de nuestro módulo

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => '{ HOST }/v4/autofacturacion/folio/91',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'PATCH',
  CURLOPT_POSTFIELDS =>'{
    "vencimiento": "2023-09-10",
    "importe": "240.00",
    "fecha": "2023-08-25",
    "iva": "16"
}',
  CURLOPT_HTTPHEADER => array(
    'F-Api-Key: Tu API key',
    'F-Secret-Key: Tu Secret key',
    'Content-Type: application/json'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

var request = require('request');
var options = {
  'method': 'PATCH',
  'url': '{ HOST }/v4/autofacturacion/folio/91',
  'headers': {
    'F-Api-Key': 'Tu API key',
    'F-Secret-Key': 'Tu Secret key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "vencimiento": "2023-09-10",
    "importe": "240.00",
    "fecha": "2023-08-25",
    "iva": "16"
  })

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

import requests
import json

url = "{ HOST }/v4/autofacturacion/folio/91"

payload = json.dumps({
  "vencimiento": "2023-09-10",
  "importe": "240.00",
  "fecha": "2023-08-25",
  "iva": "16"
})
headers = {
  'F-Api-Key': 'Tu API key',
  'F-Secret-Key': 'Tu Secret key',
  'Content-Type': 'application/json'
}

response = requests.request("PATCH", url, headers=headers, data=payload)

print(response.text)

require "uri"
require "json"
require "net/http"

url = URI("{ HOST }/v4/autofacturacion/folio/91")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Patch.new(url)
request["F-Api-Key"] = "Tu API key"
request["F-Secret-Key"] = "Tu Secret key"
request["Content-Type"] = "application/json"
request.body = JSON.dump({
  "vencimiento": "2023-09-10",
  "importe": "240.00",
  "fecha": "2023-08-25",
  "iva": "16"
})

response = http.request(request)
puts response.read_body

Respuestas al actualizar una orden

Respuesta Exitosa

{
    "response": "success",
    "message": "Registro actualizado",
    "data": {
        "id": 482,
        "vencimiento": "2023-09-10",
        "folio": 91,
        "importe": "240.00",
        "uuid": "",
        "fecha": "2023-08-25",
        "creado": "2023-06-05",
        "facturado": "no",
        "tasa": "16"
    }
}

Respuesta erronea cuando no se encuentra la orden

{
    "response": "error",
    "message": "El folio ingresado no existe"
}

Respuesta erronea cuando no se envia un campo incorrectamente

{
    "response": "error",
    "message": {
        "vencimiento": [
            "El campo vencimiento no corresponde con el formato Y-m-d."
        ]
    }
}

Aviso

El mensaje de error puede variar dependiendo el nodo en el que haya información incorrecta. Te sugerimos leer cuidadosamente el mensaje del error ya que en el mismo se indica donde es necesario corregir la información.

Actualizar múltiples órdenes

Ahora te decimos como actualizar múltiples órdenes a la vez, utilizando los mismos campos que usaste anteriormente.

 Parametro Tipo Requerido Detallles
 id Numerico Requerido

 Este dato se obtiene al listar las órdenes, es un número único e irrepetible que se asigna a tus órdenes

Ejemplo:

2958344

 vencimiento String Opcional

 Se utiliza para indicar la fecha limite que tendra el cliente para timbrar su factura

Este campo debe ingresarse con el siguiente formato:

"2023-09-28"

 importe Numerico Opcional

 Indica la cantidad de dinero correspondiente de la orden aqui podemos definir el total del ticket

Ejemplo: 123.45

NOTA: Esta cantidad siempre incluye el IVA y se calcula con el porcentaje que ingresamos en el campo 'iva'

Es decir 'importe' => 123.45    'iva' => 16

Subtotal = 106.42

Total = 17.03

 fecha String Opcional

 Se utiliza para definir la fecha en la que se realizo la venta o que generamos el ticket para nuestros clientes

Este campo debe ingresarse con el siguiente formato:

"2023-08-28"

 iva Numerico Opcional

 Con este campo podemos definir la tasa de IVA utilizado en la venta que se aplicara a el importe de la orden

Admite los siguientes valores:

16
8
4
0
exento

NOTA: Los porcentajes estan disponibles de acuerdo a los estimulos fiscales a los que corresponde nuestro RFC, puede ser posible que no aplique alguno de los porcentajes para ti, esto debes revisarlo con tu contador antes de implementarlos.

 formaDePago String Opcional

 Aquí podemos editar la forma de pago que tuvo la orden, utilizando las claves del SAT para las Formas de pago .

Ejemplo:

"01" (Efectivo)

 ish Numerico Opcional

 Esta campo es para especificar la tasa correspondiente al Impuesto Sobre el Hospedaje (ISH), aplicable a clientes del sector hotelero.

Ejemplo:

"5" = 5%

 tag String Opcional

 Se puede usar para agregar una etiqueta personalizada a la orden, lo que permite clasificarla o identificar su origen, ademas, se podra usar este elemento para configuraciones en el autofacturador.

Ejemplo:

Puede usar los tags "ONLINE" y "TIENDA" para distinguir si la orden proviene de la tienda en línea o de una sucursal física.

 objetoImpuesto String Opcional

 Se puede utilizar para definir el tipo de impuesto que aplica al concepto facturado. Si no se envía, se asignará por defecto la clave 02

Opciones:
"01": No objeto de impuesto.
"02": Si objeto de impuesto.
"03": Si objeto de impuesto y no obligado al desglose
"04": Si objeto de impuesto y no causa impuesto
"05": Si objeto del impuesto, IVA crédito PODEBI

Nota: Este campo tiene prioridad sobre otros impuestos. Si se envía con las claves 01, 03, 04 o 05, el sistema ignorará cualquier impuesto especificado en la petición, incluso si se incluyen.

Tip

De nueva cuenta se usa el metodo PATCH

Construcción de la URL

Host: https://app.facturamval.com/api (producción) / https://sandbox.facturamval.com/api (sandbox)

Endpoint: /v4/autofacturacion/multiple

Ejemplo: https://app.facturamval.com/api/v4/autofacturacion/multiple

Tip

No es posible editar ordenes que ya fueron facturasdas.

Ejemplo para actualizar múltiples órdenes de nuestro módulo

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => '{ HOST }/v4/autofacturacion/multiple',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'PATCH',
  CURLOPT_POSTFIELDS =>'[
{
    "id": 2958344,
    "fecha": "2025-02-04",
    "importe": "100.00",
    "vencimiento": "2025-02-28",
    "iva": "16",
    "formaDePago": "28"
},
{
    "id": 2958343,
    "fecha": "2025-02-03",
    "importe": "350.00",
    "vencimiento": "2025-02-28",
    "iva": "16",
    "formaDePago": "28"
}
]',
  CURLOPT_HTTPHEADER => array(
    'F-Api-Key: Tu API key',
    'F-Secret-Key: Tu Secret key',
    'Content-Type: application/json'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

var request = require('request');
var options = {
  'method': 'PATCH',
  'url': '{ HOST }/v4/autofacturacion/folio/91',
  'headers': {
    'F-Api-Key': 'Tu API key',
    'F-Secret-Key': 'Tu Secret key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify([
    {
      "id": 2958344,
      "fecha": "2025-02-04",
      "importe": "100.00",
      "vencimiento": "2025-02-28",
      "iva": "16",
      "formaDePago": "28"
    },
    {
      "id": 2958343,
      "fecha": "2025-02-03",
      "importe": "350.00",
      "vencimiento": "2025-02-28",
      "iva": "16",
      "formaDePago": "28"
    }
  ])

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

import requests
import json

url = "{ HOST }/v4/autofacturacion/folio/91"

payload = json.dumps([
  {
    "id": 2958344,
    "fecha": "2025-02-04",
    "importe": "100.00",
    "vencimiento": "2025-02-28",
    "iva": "16",
    "formaDePago": "28"
  },
  {
    "id": 2958343,
    "fecha": "2025-02-03",
    "importe": "350.00",
    "vencimiento": "2025-02-28",
    "iva": "16",
    "formaDePago": "28"
  }
])
headers = {
  'F-Api-Key': 'Tu API key',
  'F-Secret-Key': 'Tu Secret key',
  'Content-Type': 'application/json'
}

response = requests.request("PATCH", url, headers=headers, data=payload)

print(response.text)

require "uri"
require "json"
require "net/http"

url = URI("{ HOST }/v4/autofacturacion/folio/91")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Patch.new(url)
request["F-Api-Key"] = "Tu API key"
request["F-Secret-Key"] = "Tu Secret key"
request["Content-Type"] = "application/json"
request.body = JSON.dump([
  {
    "id": 2958344,
    "fecha": "2025-02-04",
    "importe": "100.00",
    "vencimiento": "2025-02-28",
    "iva": "16",
    "formaDePago": "28"
  },
  {
    "id": 2958343,
    "fecha": "2025-02-03",
    "importe": "350.00",
    "vencimiento": "2025-02-28",
    "iva": "16",
    "formaDePago": "28"
  }
])

response = http.request(request)
puts response.read_body

Respuestas al actualizar múltiples órdenes

Respuesta Exitosa

{
    "response": "success",
    "message": "Registros actualizados",
    "actualizados": [
        2958366,
        2958367
    ],
    "existentes": [],
    "inexistentes": [],
    "facturados": []
}

Respuesta erronea cuando no se encuentra la orden

{
    "response": "success",
    "message": "Registros actualizados",
    "actualizados": [],
    "existentes": [],
    "inexistentes": [
        "29586",
        "8367"
    ],
    "facturados": []
}

Respuesta erronea cuando no se envia un campo requerido

{
    "response": "error",
    "message": {
        "0.id": [
            "El campo 0.id es requerido"
        ],
        "1.id": [
            "El campo 1.id es requerido"
        ]
    }
}

Eliminar una orden

A continuación se explica como funciona el método con el cual podras eliminar una orden en especifico de tu modulo de autofacturación.

Podemos eliminar las ordenes en nuestro modulo haciendo uso de los siguientes parámetros:

 Parametro Tipo Requerido Detallles
 folio Numerico Requerido

Indica el folio que asignamos cuando cargamos la orden a el autofacturador, con este numero podemos identificarlo y acceder a el para consultarlo

Ejemplo: 77

Tip

Importante el metodo para eliminar una orden es de tipo DELETE

Construcción de la URL

Host: https://app.facturamval.com/api (producción) / https://sandbox.facturamval.com/api (sandbox)

Endpoint: /v4/autofacturacion/folio/{ID}

Ejemplo: https://app.facturamval.com/api/v4/autofacturacion/folio/91

Tip

Para probar el código de ejemplo es necesario que reemplaces el texto Tu API key por el API KEY de tu cuenta, e Tu Secret key por el SECRET KEY correspondiente. Así como cambiar los UID de los CFDIs relacionados y de receptor.

Ejemplo para eliminar una orden de nuestro módulo

<?php

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => '{ HOST }/v4/autofacturacion/folio/91',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'DELETE',
  CURLOPT_HTTPHEADER => array(
    'F-Api-Key: Tu API key',
    'F-Secret-Key: Tu Secret key'
  ),
));

$response = curl_exec($curl);

curl_close($curl);
echo $response;

var request = require('request');
var options = {
  'method': 'DELETE',
  'url': '{ HOST }/v4/autofacturacion/folio/91',
  'headers': {
    'F-Api-Key': 'Tu API key',
    'F-Secret-Key': 'Tu Secret key'
  }
};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

import requests

url = "{ HOST }/v4/autofacturacion/folio/91"

payload = {}
headers = {
  'F-Api-Key': 'Tu API key',
  'F-Secret-Key': 'Tu Secret key'
}

response = requests.request("DELETE", url, headers=headers, data=payload)

print(response.text)

require "uri"
require "net/http"

url = URI("{ HOST }/v4/autofacturacion/folio/91")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Delete.new(url)
request["F-Api-Key"] = "Tu API key"
request["F-Secret-Key"] = "Tu Secret key"

response = http.request(request)
puts response.read_body

Respuestas al eliminar una orden

Respuesta Exitosa

{
    "response": "success",
    "page": 1,
    "per_page": 100,
    "data": {
        "id": 482,
        "vencimiento": "2023-09-10",
        "folio": 91,
        "importe": "240.00",
        "uuid": "",
        "fecha": "2023-08-25",
        "creado": "2023-06-05",
        "facturado": "no",
        "tasa": "16"
    }
}

Respuesta erronea cuando no se encuentra la orden

{
    "response": "error",
    "message": "El registro no existe"
}

Aviso

El mensaje de error puede variar dependiendo el nodo en el que haya información incorrecta. Te sugerimos leer cuidadosamente el mensaje del error ya que en el mismo se indica donde es necesario corregir la información.

Last Updated:
Prev
Consultar estatus de cancelación de un CFDI
Next
Grupos de empleados