Crear factura
https://api.afer.pro/crearFactura
Crea una factura de venta con sus líneas, da de alta o actualiza el cliente de facturación y, opcionalmente, registra el cobro o sus vencimientos.
Es el endpoint principal para integrar un e-commerce o una pasarela de reservas con la facturación de Afer. En una sola llamada:
1. Cliente — si envías cliente_facturacion_fk se usa ese cliente existente; si no, se busca por CIF dentro de tu cuenta y se actualiza, o se crea uno nuevo con código contable propio.
2. Factura — se crea la cabecera en la serie indicada con numeración automática y fecha de hoy (salvo modo borrador).
3. Líneas — se insertan los detalles; si una línea referencia un artículo en modo venta, se genera su movimiento de inventario y se consolida el stock.
4. Cobro — si envías vencimientos se insertan tal cual; si envías pedido.importe_pagado se registra un único pago con su método y contrapartida; si no envías nada, se generan los vencimientos automáticos según la configuración del cliente.
Si tu cuenta tiene VERI*FACTU vigente y la factura no es borrador, se bloquea contra modificación y se envía automáticamente al registro de facturación de la AEAT.
Envía tus claves API en las cabeceras X-API-KEY y X-API-SECRET. La cuenta sobre la que se opera se resuelve automáticamente a partir de la clave. Cómo obtener tus claves →
Parámetros del cuerpo
El cuerpo de la petición es un objeto JSON con Content-Type: application/json.
cliente_facturacion_fkintopcional | ID de un cliente de facturación ya existente en tu cuenta. Si se envía y es válido, se factura a ese cliente y se ignora el objeto cliente. |
clienteobjectobligatorio | Datos del cliente de facturación. Obligatorio si no se envía cliente_facturacion_fk. Si ya existe un cliente con el mismo cif en tu cuenta, se actualiza; si no, se crea. |
nombre_fiscalstringobligatorio | Nombre fiscal. Se guarda en mayúsculas. |
cifstringopcional | CIF/NIF. Es la clave de deduplicación: sin él, cada llamada crea un cliente nuevo. |
direccionstringopcional | Dirección fiscal. |
cpstringopcional | Código postal. |
poblacionstringopcional | Población. |
provinciastringopcional | Provincia. |
paisstringopcional | País (nombre o código, p. ej. DE). |
telefonostringopcional | Teléfono de contacto. |
emailstringopcional | Email de contacto. |
ibanstringopcional | IBAN del cliente. Se guarda cifrado. |
etiqueta_crmstringopcional | IDs de etiquetas de CRM separados por coma. Se vinculan al cliente sin duplicar. |
nombre_envio, direccion_envio, cp_envio…stringopcional | Campos de dirección de envío (nombre_envio, direccion_envio, num_calle_envio, num_piso_envio, cp_envio, poblacion_envio, provincia_envio, pais_envio). El país de envío acepta nombre o código y se normaliza. |
seriestringobligatorio | Código de la serie de facturación de tu cuenta (p. ej. "A"). La numeración se asigna automáticamente dentro de la serie. |
borradorboolopcional | Por defecto false. Con true la factura se crea sin número y sin bloqueo VERI*FACTU, pendiente de emitir desde Afer. |
terminal_fkintopcional | Terminal de venta al que se asocia la factura. |
pedidoobjectobligatorio | Cabecera de la operación. |
obrastringobligatorio | Concepto o referencia de la operación (p. ej. "Pedido web 006520"). |
detalles_operacionstringopcional | Observaciones de la operación. Admite HTML. |
porciento_retencionnumberopcional | Porcentaje de retención aplicado a la factura. Por defecto 0. |
promo_codestringopcional | Código promocional aplicado. |
importe_pagadonumberopcional | Importe ya cobrado. Si se envía, se registra un pago con fecha de hoy. Ignorado si envías vencimientos. |
metodo_pago_fkintopcional | Método de pago del cobro. Se valida contra los métodos de tu cuenta (o los globales). 8 = Stripe: calcula y registra la comisión de pasarela automáticamente. Se admite el alias legado forma_pago. |
contrapartida_pago_fkintopcional | Contrapartida de tesorería donde se abona el cobro. Debe pertenecer a tu cuenta. Para Stripe, si no se envía se usa la contrapartida de tipo stripe configurada. |
contrapartida_gastos_fkintopcional | Contrapartida de gastos para comisiones de pasarela. Para Stripe, si no se envía se usa la subcuenta de gastos configurada en tu cuenta. |
auth_code_pagostringopcional | Referencia externa del cobro (p. ej. el payment_intent de Stripe). Se guarda como ID de seguimiento. |
detallesarrayobligatorio | Líneas de la factura. |
cantidadnumberobligatorio | Unidades. Admite hasta 3 decimales. |
descripcionstringobligatorio | Descripción de la línea. |
importe_unitarionumberobligatorio | Precio unitario sin IVA. |
ivanumberobligatorio | Tipo de IVA de la línea (p. ej. 21). |
descuentonumberopcional | Porcentaje de descuento de la línea. |
articulo_fkintopcional | ID del artículo de tu catálogo. Con artículo en modo venta se descuenta stock. 0 para líneas libres. |
variacion_articulo_fkintopcional | ID de la variación del artículo (talla, modelo…). 0 si no aplica. |
descripcion_ampliadastringopcional | Texto ampliado de la línea. |
startDatedateopcional | Inicio del período, para líneas de alquiler (YYYY-MM-DD). Cuenta para la disponibilidad. |
endDatedateopcional | Fin del período, para líneas de alquiler (YYYY-MM-DD). |
vencimientosarrayopcional | Vencimientos explícitos de la factura. Si se envían, tienen prioridad sobre pedido.importe_pagado y sobre la generación automática. |
fecha_vencimientodateobligatorio | Fecha del vencimiento (YYYY-MM-DD). |
importe_vencimientonumberobligatorio | Importe del vencimiento. |
importe_pagonumberobligatorio | Importe ya pagado de este vencimiento (0 si está pendiente). |
fecha_pagodateobligatorio | Fecha del pago, si lo hay. |
metodo_pago_fkintopcional | Método de pago. Por defecto 1. |
contrapartida_pago_fkintopcional | Contrapartida de tesorería del pago. |
usuario_pago_fkintopcional | Usuario que registra el pago. |
terminal_arqueo_fkintopcional | Terminal de arqueo asociado al pago. |
Ejemplo de petición
curl -X POST 'https://api.afer.pro/crearFactura' \
-H 'Content-Type: application/json' \
-H 'X-API-KEY: afer_tk_TU_TOKEN' \
-H 'X-API-SECRET: afer_sk_TU_SECRET' \
-d '{
"cliente": {
"nombre_fiscal": "Franz-Josef Thönnißen",
"cif": "L796KFKR4",
"direccion": "Lohfelder Str. 86",
"poblacion": "Bad Honnef",
"pais": "DE",
"telefono": "+491704856051",
"email": "franz-josef@ejemplo.com"
},
"serie": "A",
"pedido": {
"obra": "Pedido web 006520",
"metodo_pago_fk": 8,
"auth_code_pago": "pi_3U2EgPDWXi39vPE03",
"importe_pagado": 158,
"detalles_operacion": "<h2>Recogida en tienda</h2><p>05/09/2026 9:30</p>"
},
"detalles": [
{
"cantidad": 1,
"articulo_fk": 52087,
"variacion_articulo_fk": 524997,
"descripcion": "CANNONDALE SYNAPSE CARBON / 58",
"importe_unitario": 123.9669421,
"descuento": 0,
"iva": 21,
"startDate": "2026-09-05",
"endDate": "2026-09-10"
},
{
"cantidad": 1,
"articulo_fk": 344722,
"variacion_articulo_fk": 0,
"descripcion": "Dual Shimano SPD Flat Pedals",
"importe_unitario": 6.6115702,
"descuento": 0,
"iva": 21,
"startDate": "2026-09-05",
"endDate": "2026-09-10"
}
]
}'
<?php
$data = [
'cliente' => [
'nombre_fiscal' => 'Franz-Josef Thönnißen',
'cif' => 'L796KFKR4',
'direccion' => 'Lohfelder Str. 86',
'poblacion' => 'Bad Honnef',
'pais' => 'DE',
'telefono' => '+491704856051',
'email' => 'franz-josef@ejemplo.com',
],
'serie' => 'A',
'pedido' => [
'obra' => 'Pedido web 006520',
'metodo_pago_fk' => 8,
'auth_code_pago' => 'pi_3U2EgPDWXi39vPE03',
'importe_pagado' => 158.0,
'detalles_operacion' => '<h2>Recogida en tienda</h2><p>05/09/2026 9:30</p>',
],
'detalles' => [
0 => [
'cantidad' => 1,
'articulo_fk' => 52087,
'variacion_articulo_fk' => 524997,
'descripcion' => 'CANNONDALE SYNAPSE CARBON / 58',
'importe_unitario' => 123.9669421,
'descuento' => 0,
'iva' => 21,
'startDate' => '2026-09-05',
'endDate' => '2026-09-10',
],
1 => [
'cantidad' => 1,
'articulo_fk' => 344722,
'variacion_articulo_fk' => 0,
'descripcion' => 'Dual Shimano SPD Flat Pedals',
'importe_unitario' => 6.6115702,
'descuento' => 0,
'iva' => 21,
'startDate' => '2026-09-05',
'endDate' => '2026-09-10',
],
],
];
$ch = curl_init('https://api.afer.pro/crearFactura');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'X-API-KEY: afer_tk_TU_TOKEN',
'X-API-SECRET: afer_sk_TU_SECRET',
]);
$respuesta = json_decode(curl_exec($ch), true);
curl_close($ch);
const respuesta = await fetch('https://api.afer.pro/crearFactura', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': 'afer_tk_TU_TOKEN',
'X-API-SECRET': 'afer_sk_TU_SECRET'
},
body: JSON.stringify({
"cliente": {
"nombre_fiscal": "Franz-Josef Thönnißen",
"cif": "L796KFKR4",
"direccion": "Lohfelder Str. 86",
"poblacion": "Bad Honnef",
"pais": "DE",
"telefono": "+491704856051",
"email": "franz-josef@ejemplo.com"
},
"serie": "A",
"pedido": {
"obra": "Pedido web 006520",
"metodo_pago_fk": 8,
"auth_code_pago": "pi_3U2EgPDWXi39vPE03",
"importe_pagado": 158,
"detalles_operacion": "<h2>Recogida en tienda</h2><p>05/09/2026 9:30</p>"
},
"detalles": [
{
"cantidad": 1,
"articulo_fk": 52087,
"variacion_articulo_fk": 524997,
"descripcion": "CANNONDALE SYNAPSE CARBON / 58",
"importe_unitario": 123.9669421,
"descuento": 0,
"iva": 21,
"startDate": "2026-09-05",
"endDate": "2026-09-10"
},
{
"cantidad": 1,
"articulo_fk": 344722,
"variacion_articulo_fk": 0,
"descripcion": "Dual Shimano SPD Flat Pedals",
"importe_unitario": 6.6115702,
"descuento": 0,
"iva": 21,
"startDate": "2026-09-05",
"endDate": "2026-09-10"
}
]
})
});
const resultado = await respuesta.json();
Respuesta
Devuelve el identificador cifrado de la factura creada. Guárdalo si necesitas referenciarla más adelante.
{
"errorCode": 200,
"errorMsg": "",
"data": "aBc123XyZ456…"
}
Errores
| Caso | Resultado |
|---|---|
Sin cliente ni cliente_facturacion_fk válido |
errorCode 422, errorMsg "Error on service call: Cliente no encontrado." |
- Los importes unitarios van sin IVA; los totales, el IVA y el saldo los calcula Afer al cerrar la factura.
- Si el cobro cubre el total (saldo ≤ 0,01 €), la factura queda marcada como cobrada automáticamente.
- Con VERI*FACTU vigente la factura emitida queda bloqueada y se envía a la AEAT: revisa los datos antes de llamar, no podrás modificarla después.
- Las líneas con
startDate/endDatecomputan como reservas en consultarDisponibilidadArticulos.