Comprobante de Pago
El comprobante de tipo Pago, también llamado Recibo Electrónico de Pago (REP), o simplemente complemento de pago se utiliza para dar constancia fiscal de que la empresa o la persona recibió un pago por una mercancía o servicio entregado con anterioridad.
Para emitir un comprobante de tipo Pago, debe existir un Comprobante de Ingreso que se haya creado al momento de
la entrega de la mercancía o servicio, y cuyo método de pago se haya registrado el valor "PPD"
(Pago en Parcialidades o Diferido).
Ejemplos
A continuación se enlistan algunos casos de uso comunes.
Para conocer a fondo todas las opciones disponibles al crear un Comprobante de Pago, descripciones detalladas de cada campo y los catálogos más utilizados consulta la referencia del método Crear Factura, y posteriormente haz clic sobre el tipo de factura Pago.
Pago total de una factura pendiente
En este ejemplo, se recibe un sólo pago para liquidar el total de una factura pendiente de pago por $345.60 MXN.
- Node.js
- C#
- Java
- PHP
- cURL
import Facturapi from 'facturapi'
const facturapi = new Facturapi('sk_test_API_KEY');
const invoice = await facturapi.invoices.create({
type: 'P',
customer: {
legal_name: 'Dunder Mifflin',
email: 'email@example.com',
tax_id: 'ABC101010111',
tax_system: '601',
address: {
zip: '85900'
}
},
complements: [
{
type: 'pago',
data: [{
payment_form: '28', // Tarjeta de Crédito
related_documents: [
{
uuid: '39c85a3f-275b-4341-b259-e8971d9f8a94',
amount: 345.60,
installment: 1,
last_balance: 345.60,
taxes: [
{
base: 297.93,
type: 'IVA',
rate: 0.16
}
]
}
]
}]
}
]
});
var facturapi = new FacturapiClient("sk_test_API_KEY");
var invoice = await facturapi.Invoice.CreateAsync(new Dictionary<string, object>
{
["type"] = "P",
["customer"] = new Dictionary<string, object>
{
["legal_name"] = "Dunder Mifflin",
["email"] = "email@example.com",
["tax_id"] = "ABC101010111",
["tax_system"] = "601",
["address"] = new Dictionary<string, object>
{
["zip"] = "85900"
}
},
["complements"] = new Dictionary<string, object>[]
{
new Dictionary<string, object>
{
["type"] = "pago",
["data"] = new Dictionary<string, object>[]
{
new Dictionary<string, object>
{
["payment_form"] = "28", // Tarjeta de Crédito
["related_documents"] = new Dictionary<string, object>[]
{
new Dictionary<string, object>
{
["uuid"] = "39c85a3f-275b-4341-b259-e8971d9f8a94",
["amount"] = 345.60,
["installment"] = 1,
["last_balance"] = 345.60,
["taxes"] = new Dictionary<string, object>[]
{
new Dictionary<string, object>
{
["base"] = 297.93,
["type"] = "IVA",
["rate"] = 0.16
}
}
}
}
}
}
}
}
});
import io.facturapi.Facturapi;
import java.util.List;
import java.util.Map;
Facturapi facturapi = new Facturapi("sk_test_API_KEY");
var invoice = facturapi.invoices().create(Map.of(
"type", "P",
"customer", Map.of(
"legal_name", "Dunder Mifflin",
"email", "email@example.com",
"tax_id", "ABC101010111",
"tax_system", "601",
"address", Map.of("zip", "85900")
),
"complements", List.of(Map.of(
"type", "pago",
"data", List.of(Map.of(
"payment_form", "28",
"related_documents", List.of(Map.of(
"uuid", "39c85a3f-275b-4341-b259-e8971d9f8a94",
"amount", 345.60,
"installment", 1,
"last_balance", 345.60,
"taxes", List.of(Map.of(
"base", 297.93,
"type", "IVA",
"rate", 0.16
))
))
))
))
));
$facturapi = new Facturapi("sk_test_API_KEY");
$invoice = $facturapi->Invoices->create([
"type" => "P",
"customer" => [
"legal_name" => "Dunder Mifflin",
"email" => "email@example.com",
"tax_id" => "ABC101010111",
"tax_system" => "601",
"address" => [
"zip" => "85900"
]
],
"complements" => [
[
"type" => "pago",
"data" => [
[
"payment_form" => "28", // Tarjeta de Crédito
"related_documents" => [
[
"uuid" => "39c85a3f-275b-4341-b259-e8971d9f8a94",
"amount" => 345.60,
"installment" => 1,
"last_balance" => 345.60,
"taxes" => [
[
"base" => 297.93,
"type" => "IVA",
"rate" => 0.16
]
]
]
]
]
]
]
]
]);
curl https://www.facturapi.io/v2/invoices \
-H "Authorization: Bearer sk_test_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "P",
"customer": {
"legal_name": "Dunder Mifflin",
"email": "email@example.com",
"tax_id": "ABC101010111",
"tax_system": "601",
"address": {
"zip": "85900"
}
},
"complements": [
{
"type": "pago",
"data": [{
"payment_form": "28",
"related_documents": [
{
"uuid": "39c85a3f-275b-4341-b259-e8971d9f8a94",
"amount": 345.60,
"installment": 1,
"last_balance": 345.60,
"taxes": [
{
"base": 297.93,
"type": "IVA",
"rate": 0.16
}
]
}
]
}]
}
]
}'
Pago en parcialidades de una factura pendiente
En este ejemplo, se reciben $100 MXN como pago por la segunda parcialidad de una factura pendiente de pago cuyo total era de $345.60 MXN. Se considera que en la primera parcialidad también se pagaron $100 MXN.
- Node.js
- C#
- PHP
- cURL
import Facturapi from 'facturapi'
const facturapi = new Facturapi('sk_test_API_KEY');
const invoice = await facturapi.invoices.create({
type: 'P',
customer: {
legal_name: 'Dunder Mifflin',
email: 'email@example.com',
tax_id: 'ABC101010111',
tax_system: '601',
address: {
zip: '85900'
}
},
complements: [
{
type: 'pago',
data: [{
payment_form: '28', // Tarjeta de Crédito
related_documents: [
{
uuid: '39c85a3f-275b-4341-b259-e8971d9f8a94',
amount: 100, // Monto de la factura relacionada que se paga en la presente parcialidad
installment: 2, // Esta es la segunda parcialidad
last_balance: 245.60, // Saldo insoluto de la primera parcialidad
taxes: [
{
base: 86.21, // Base de IVA de la segunda parcialidad
type: 'IVA',
rate: 0.16
}
]
}
]
}]
}
]
});
var facturapi = new FacturapiClient("sk_test_API_KEY");
var invoice = await facturapi.Invoice.CreateAsync(new Dictionary<string, object>
{
["type"] = "P",
["customer"] = new Dictionary<string, object>
{
["legal_name"] = "Dunder Mifflin",
["email"] = "email@example.com",
["tax_id"] = "ABC101010111",
["tax_system"] = "601",
["address"] = new Dictionary<string, object>
{
["zip"] = "85900"
}
},
["complements"] = new Dictionary<string, object>[]
{
new Dictionary<string, object>
{
["type"] = "pago",
["data"] = new Dictionary<string, object>[]
{
new Dictionary<string, object>
{
["payment_form"] = "28", // Tarjeta de Crédito
["related_documents"] = new Dictionary<string, object>[]
{
new Dictionary<string, object>
{
["uuid"] = "39c85a3f-275b-4341-b259-e8971d9f8a94",
["amount"] = 100, // Monto de la factura relacionada que se paga en la presente parcialidad
["installment"] = 2, // Esta es la segunda parcialidad
["last_balance"] = 245.60, // Saldo insoluto de la primera parcialidad
["taxes"] = new Dictionary<string, object>[]
{
new Dictionary<string, object>
{
["base"] = 86.21, // Base de IVA de la segunda parcialidad
["type"] = "IVA",
["rate"] = 0.16
}
}
}
}
}
}
}
}
});
$facturapi = new Facturapi("sk_test_API_KEY");
$invoice = $facturapi->Invoices->create([
"type" => "P",
"customer" => [
"legal_name" => "Dunder Mifflin",
"email" => "email@example.com",
"tax_id" => "ABC101010111",
"tax_system" => "601",
"address" => [
"zip" => "85900"
]
],
"complements" => [
[
"type" => "pago",
"data" => [
[
"payment_form" => "28", // Tarjeta de Crédito
"related_documents" => [
[
"uuid" => "39c85a3f-275b-4341-b259-e8971d9f8a94",
"amount" => 100, // Monto de la factura relacionada que se paga en la presente parcialidad
"installment" => 2, // Esta es la segunda parcialidad
"last_balance" => 245.60, // Saldo insoluto de la primera parcialidad
"taxes" => [
[
"base" => 86.21, // Base de IVA de la segunda parcialidad
"type" => "IVA",
"rate" => 0.16
]
]
]
]
]
]
]
]
]);
curl https://www.facturapi.io/v2/invoices \
-H "Authorization: Bearer sk_test_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "P",
"customer": {
"legal_name": "Dunder Mifflin",
"email": "email@example.com",
"tax_id": "ABC101010111",
"tax_system": "601",
"address": {
"zip": "85900"
}
},
"complements": [
{
"type": "pago",
"data": [{
"payment_form": "28", // Tarjeta de Crédito
"related_documents": [
{
"uuid": "39c85a3f-275b-4341-b259-e8971d9f8a94",
"amount": 100, // Monto de la factura relacionada que se paga en la presente parcialidad
"installment": 2, // Esta es la segunda parcialidad
"last_balance": 245.60, // Saldo insoluto de la primera parcialidad
"taxes": [
{
"base": 86.21, // Base de IVA de la segunda parcialidad
"type": "IVA",
"rate": 0.16
}
]
}
]
}]
}
]
}'
Resumen de pago
Para construir los related_documents de un Complemento de Pago necesitas, por cada factura
relacionada: el número de parcialidad que corresponde, el saldo anterior y el desglose de impuestos
prorrateado al monto que se paga. Calcular estos valores a mano es propenso a errores, sobre todo en
pagos en varias parcialidades o con retenciones.
El endpoint Resumen de pago hace ese cálculo
por ti: devuelve el objeto related_document listo para agregarse al complemento.
import Facturapi from 'facturapi'
const facturapi = new Facturapi('sk_test_API_KEY');
// Monto que se paga de esta factura, en la divisa de la factura.
// No puede exceder el saldo pendiente (amount_due).
const summary = await facturapi.invoices.paymentSummary(
'58e93bd8e86eb318b019743d',
{ amount: 100 }
);
// El resumen es un elemento de related_documents listo para usarse
const invoice = await facturapi.invoices.create({
type: 'P',
customer: customer.id,
complements: [
{
type: 'pago',
data: [
{
payment_form: '28',
related_documents: [summary]
}
]
}
]
});
Cada resumen contiene, listo para el CFDI: uuid, installment (la parcialidad
que corresponde según el historial de pagos), last_balance (el saldo anterior),
amount (el monto pagado en esta parcialidad) y taxes con las bases e impuestos
ya prorrateados al monto pagado. No necesitas mapear nada: el objeto completo va
como elemento de related_documents.
Un pago que cubre varias facturas
Cuando un mismo pago liquida varias facturas, pide un resumen por factura con el monto que le corresponde a cada una y arma el complemento con todos los resúmenes:
import Facturapi from 'facturapi'
const facturapi = new Facturapi('sk_test_API_KEY');
// Los montos que decide el negocio: cuánto se abona a cada factura.
const pagos = [
{ invoiceId: '58e93bd8e86eb318b019743d', amount: 100 },
{ invoiceId: '7f104ce9f97eb428c130854e', amount: 250 }
];
const related_documents = await Promise.all(
pagos.map(({ invoiceId, amount }) =>
facturapi.invoices.paymentSummary(invoiceId, { amount })
)
);
const invoice = await facturapi.invoices.create({
type: 'P',
customer: customer.id,
complements: [
{
type: 'pago',
data: [
{
payment_form: '28',
related_documents
}
]
}
]
});
Si el monto excede el saldo de alguna factura, el endpoint responde un error
(amount_exceeds_related_document_balance) antes de crear nada. Lo mismo sucede
si la factura no es candidata a pago: el endpoint solo acepta facturas de ingreso
timbradas con método de pago PPD que sigan vigentes.