Saltar al contenido
Secciones de la documentación

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

  1. Al cobrar, tu sistema manda el ticket a POST /selfservice/ticket. Queda en estatus 1, sin facturar.
  2. Tu cliente entra a tu portal, escribe la referencia y el monto del ticket, y se factura. El ticket pasa a estatus 2.
  3. Lo que nadie facturó entra a tu factura global y pasa a estatus 3.
  4. Si hay una devolución o una venta cancelada, cambia el ticket a estatus 4 con POST /selfservice/ticketstatus para que ya no se pueda facturar.

Estatus de un ticket

EstatusQué significa¿Se puede facturar?¿Se pone por la API?
1Sin facturar.Sí.Sí.
2Facturado por tu cliente.No.No: lo pone el timbrado.
3En una factura global.No.No: lo pone la global.
4Cancelado o devuelto.No.Sí.
5Por refacturar: se facturó con datos equivocados.Sí, dentro del mes de su factura anterior.Sí.
6Anulado.No.Sí.

Registrar un ticket

POST/selfservice/ticket

El 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
curl -sS -X POST "$FD_API/selfservice/ticket" \
  -H "X-Api-Key: $FD_API_KEY" \
  --data-urlencode "json@ticket.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" }
        ]
      }
    }
  ]
}
Referenciastringobligatorio
El folio del ticket que tu cliente va a escribir en el portal. Mínimo 5 caracteres.
Fechastringobligatorio
AAAA-MM-DD. No se aceptan tickets de más de 13 meses atrás.
FechaLimitestringobligatorio
Hasta cuándo se puede facturar, AAAA-MM-DD hh:mm:ss. Ponle hora: 2026-11-30 sin hora vence al empezar ese día, y sin FechaLimite el ticket nace vencido.
Moneda, TipoCambiostringobligatorio
MXN con 1, o la moneda y su tipo de cambio del día.
Subtotal, Totalstringobligatorio
Distintos de cero.
Ivastringobligatorio
Mándalo siempre, aunque sea "0.00".
Descuentostringopcional
Descuento del ticket.
Sucursalstringopcional
Número de sucursal.
Plataformastringopcional
Texto libre, por ejemplo TPV.
Correostringopcional
Correo de tu cliente.
FormaPagostringopcional
Clave de c_FormaPago.
Seriestringopcional
Al facturarse se reemplaza por la serie de la factura.
Conceptosarrayopcional
Los mismos campos que en Crear un CFDI, con Impuestos.Traslados y Impuestos.Retenciones, más extra1 a extra10 (en minúsculas).
codeCuándo pasa
400No llegó el parámetro json.
5501Referencia vacía o de menos de 5 caracteres. También sale si el JSON está mal formado.
5503Falta Fecha o es anterior a 13 meses.
5504Falta Moneda.
5505Falta TipoCambio.
5506Subtotal es cero.
5507Total es cero.
520Ticket 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

GET/selfservice/ticket

Con 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.

200
{
  "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

GET/selfservice/ticketlist
GET/selfservice/ticketlistdetailed

Parámetros (query)

fechaini, fechafinstringobligatorio
Rango de fechas del ticket, AAAA-MM-DD, incluidos.
estatusintegercondicional
Un estatus de 1 a 6. Obligatorio en ticketlist, opcional en ticketlistdetailed.
contabilizadostringopcional
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

POST/selfservice/ticketstatus

Con 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[].

200
{
  "message": "Ticket updated. New Status: 4",
  "code": 200,
  "tickets": [
    { "fecha": "2026-11-03", "monto_total": 116.0, "estatus_anterior": 1, "estatus": 4, "resultado": "updated" }
  ]
}
  • resultado es updated, unchanged (ya tenía ese estatus) o rejected, con el motivo en motivo.
  • 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 code 409 con tickets[]: los que dicen updated sí quedaron.
  • code 503 «The service is busy» es que otra operación de tu cuenta tenía el turno: reintenta en unos segundos.

Marcar como contabilizado

POST/selfservice/ticketcontabilizado

Con 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

POST/selfservice/ticketdelete

Con 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.