Autofactura (kiosko)
Tu punto de venta registra cada ticket con la API y tu cliente lo factura solo en tu portal de autofactura, buscándolo por su referencia y su monto. Estas rutas no usan folios ni créditos.
Cómo funciona
- Al cobrar, tu sistema manda el ticket a
POST /selfservice/ticket. Queda en estatus 1, sin facturar. - Tu cliente entra a tu portal, escribe la referencia y el monto del ticket, y se factura. El ticket pasa a estatus 2.
- Lo que nadie facturó entra a tu factura global y pasa a estatus 3.
- Si hay una devolución o una venta cancelada, cambia el ticket a estatus 4 con
POST /selfservice/ticketstatuspara que ya no se pueda facturar.
Estatus de un ticket
| Estatus | Qué significa | ¿Se puede facturar? | ¿Se pone por la API? |
|---|---|---|---|
| 1 | Sin facturar. | Sí. | Sí. |
| 2 | Facturado por tu cliente. | No. | No: lo pone el timbrado. |
| 3 | En una factura global. | No. | No: lo pone la global. |
| 4 | Cancelado o devuelto. | No. | Sí. |
| 5 | Por refacturar: se facturó con datos equivocados. | Sí, dentro del mes de su factura anterior. | Sí. |
| 6 | Anulado. | No. | Sí. |
Registrar un ticket
/selfservice/ticketEl ticket va como texto JSON en el parámetro json de un formulario. Responde { "message": "Ticket created successfully", "code": 200 }; para ver el ticket guardado, consúltalo con GET /selfservice/ticket.
curl -sS -X POST "$FD_API/selfservice/ticket" \
-H "X-Api-Key: $FD_API_KEY" \
--data-urlencode "json@ticket.json"{
"Referencia": "POS-000123",
"Fecha": "2026-11-03",
"FechaLimite": "2026-11-30 23:59:59",
"Sucursal": "1",
"Plataforma": "TPV",
"Moneda": "MXN",
"TipoCambio": "1",
"Subtotal": "100.00",
"Descuento": "0.00",
"Iva": "16.00",
"Total": "116.00",
"FormaPago": "01",
"Conceptos": [
{
"ClaveProdServ": "50192100",
"NoIdentificacion": "SKU-001",
"Cantidad": "1",
"ClaveUnidad": "H87",
"Unidad": "Pieza",
"Descripcion": "Producto de prueba",
"ValorUnitario": "100.00",
"Importe": "100.00",
"Descuento": "0.00",
"Impuestos": {
"Traslados": [
{ "Base": "100.00", "Impuesto": "002", "TipoFactor": "Tasa", "TasaOCuota": "0.160000", "Importe": "16.00" }
]
}
}
]
}Referencia- El folio del ticket que tu cliente va a escribir en el portal. Mínimo 5 caracteres.
FechaAAAA-MM-DD. No se aceptan tickets de más de 13 meses atrás.FechaLimite- Hasta cuándo se puede facturar,
AAAA-MM-DD hh:mm:ss. Ponle hora:2026-11-30sin hora vence al empezar ese día, y sinFechaLimiteel ticket nace vencido. Moneda, TipoCambioMXNcon1, o la moneda y su tipo de cambio del día.Subtotal, Total- Distintos de cero.
Iva- Mándalo siempre, aunque sea
"0.00". Descuento- Descuento del ticket.
Sucursal- Número de sucursal.
Plataforma- Texto libre, por ejemplo
TPV. Correo- Correo de tu cliente.
FormaPago- Clave de c_FormaPago.
Serie- Al facturarse se reemplaza por la serie de la factura.
Conceptos- Los mismos campos que en Crear un CFDI, con
Impuestos.TrasladosyImpuestos.Retenciones, másextra1aextra10(en minúsculas).
| code | Cuándo pasa |
|---|---|
| 400 | No llegó el parámetro json. |
| 5501 | Referencia vacía o de menos de 5 caracteres. También sale si el JSON está mal formado. |
| 5503 | Falta Fecha o es anterior a 13 meses. |
| 5504 | Falta Moneda. |
| 5505 | Falta TipoCambio. |
| 5506 | Subtotal es cero. |
| 5507 | Total es cero. |
| 520 | Ticket duplicado: ya existe esa referencia con ese total. |
La API no revisa que los totales cuadren con los conceptos: mándalos cuadrados para que la factura de tu cliente pase.
Consultar un ticket
/selfservice/ticketCon los parámetros referencia, fecha (AAAA-MM-DD) y monto en la URL. Si se facturó, trae el UUID, la serie, el folio y el receptor.
{
"code": "200",
"message": "Ticket encontrado",
"data": {
"referencia": "POS-000123",
"fecha": "2026-11-03",
"fecha_limite": "2026-11-30 23:59:59",
"monto_total": "116.000000",
"estatus": "2",
"uuid": "A1B2C3D4-E5F6-4A7B-8C9D-0E1F2A3B4C5D",
"serie": "K",
"folio": "1001",
"receptor_rfc": "XIA190128J61",
"receptor_nombre": "XENON INDUSTRIAL ARTICLES",
"contabilizado": null
}
}Si no existe, responde HTTP 200 con { "code": "404", "message": "No se encuentra el ticket." }. Aquí code es texto.
Listas de tickets
/selfservice/ticketlist/selfservice/ticketlistdetailedParámetros (query)
fechaini, fechafin- Rango de fechas del ticket,
AAAA-MM-DD, incluidos. estatus- Un estatus de 1 a 6. Obligatorio en
ticketlist, opcional enticketlistdetailed. contabilizado- Filtra por el valor que marcaste con
ticketcontabilizado.
ticketlistdetailed agrega a cada ticket su id y sus conceptos en detalle, con sus impuestos en impuesto. Las listas no tienen paginación: usa rangos cortos, sobre todo con la detallada. Sin resultados responden HTTP 200 con code "404".
Cambiar el estatus
/selfservice/ticketstatusCon referencia y estatus en el cuerpo (1, 4, 5 o 6; el 2 y el 3 solo los pone la facturación). Cambia todos los tickets de tu cuenta con esa referencia, uno por uno, y te dice qué pasó con cada uno en tickets[].
{
"message": "Ticket updated. New Status: 4",
"code": 200,
"tickets": [
{ "fecha": "2026-11-03", "monto_total": 116.0, "estatus_anterior": 1, "estatus": 4, "resultado": "updated" }
]
}resultadoesupdated,unchanged(ya tenía ese estatus) orejected, con el motivo enmotivo.- No se cambia un ticket ya facturado, uno que tu cliente está facturando en ese momento ni uno que está entrando a una factura global.
- Si algunos se cambiaron y otros no, responde
code409 contickets[]: los que dicenupdatedsí quedaron. code503 «The service is busy» es que otra operación de tu cuenta tenía el turno: reintenta en unos segundos.
Marcar como contabilizado
/selfservice/ticketcontabilizadoCon referencia y contabilizado en el cuerpo, guarda un texto libre de hasta 20 caracteres (por ejemplo 1, SI o un número de póliza) en todos los tickets con esa referencia. Sin contabilizado, borra el valor. Sirve para filtrar las listas.
Eliminar un ticket
/selfservice/ticketdeleteCon referencia y monto_total en el cuerpo. Solo se elimina un ticket en estatus 1 que nadie esté facturando. Después puedes volver a registrar esa misma referencia y ese monto. La respuesta trae tickets[] con resultado deleted o rejected.
Revisado contra la API v5 en producción el 2026-11-03.