Facturación asíncrona
Cuando el tamaño de tus facturas es muy grande, o necesitas facturar muchas facturas al mismo tiempo, es recomendable (y en algunos casos requerido) utilizar la facturación asíncrona. Esto te permite registrar una factura en Facturapi y recibir una respuesta inmediata con el objeto Invoice y su ID, pero sin timbrar todavía. El timbrado de la factura se realiza en segundo plano, y puedes consultar el estado de la factura en cualquier momento por medio del método de obtener factura.
Recuperación automática tras un error temporal
Al crear una factura de forma síncrona, el SAT o el proveedor de certificación puede devolver un error temporal después de haber timbrado el CFDI. Cuando Facturapi detecta uno de estos casos, conserva la factura con status: "pending" y responde con el código HTTP 202 Accepted en lugar de devolver un error definitivo. Esta respuesta significa que la solicitud fue aceptada, pero su procesamiento todavía no ha terminado.
Facturapi intentará recuperar el CFDI automáticamente hasta 5 veces, con un intervalo de 10 minutos entre intentos. Los intentos ocurren aproximadamente 10, 20, 30, 40 y 50 minutos después de la respuesta inicial.
- Si Facturapi recupera el CFDI, la factura cambia a
status: "valid", se guardan su UUID y timbre, y se envía el webhookinvoice.status_updated. - Si no es posible recuperarlo después del quinto intento, la factura cambia a
status: "failed"y no se realizan más intentos.
Mientras la factura permanezca en pending, no vuelvas a crearla ni asignes su folio a otro comprobante. Puedes consultar su estado mediante el método de obtener factura o suscribirte al webhook invoice.status_updated.
Crear una factura asíncrona
Una factura se creará de manera asíncrona en cualquiera de estos 2 casos:
- Si se envía el parámetro
asynccon el valortrueal crear la factura. - Si el tamaño de la información enviada excede los 2MB (CFDIs con alrededor de 5,000 elementos o con un complemento de carta porte muy extenso).
En cualquiera de los 2 casos recibirás el objeto invoice como respuesta, con el campo status en pending. Esto significa que la factura se está procesando en segundo plano. Mientras esto ocurre, es importante
señalar que los campos stamp y uuid serán null. Una vez timbrada la factura, el campo status cambiará a valid y se llenarán los campos stamp y uuid con la información del timbrado.
Petición
- Node.js
- C#
- Java
- PHP
- cURL
const invoice = await facturapi.invoices.create({
customer: {
legal_name: 'Dunder Mifflin',
email: 'email@example.com',
tax_id: 'ABC101010111',
tax_system: '601',
address: {
zip: '85900'
}
},
items: [{
quantity: 2,
product: {
description: 'Ukelele',
product_key: '60131324', // ClaveProdServ del SAT
price: 345.60,
taxes: [
{
type: 'IVA',
rate: 0.16
}
]
}
}],
use: 'G01',
payment_form: "28" // "Tarjeta de débito"
}, { async: true });
var invoice = await facturapi.Invoice.CreateAsync(new Dictionary<string, object>
{
["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"
},
},
["items"] = new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
["quantity"] = 2,
["product"] = new Dictionary<string, object>
{
["description"] = "Ukelele",
["product_key"] = "60131324",
["price"] = 345.60,
["taxes"] = new List<Dictionary<string, object>>
{
new Dictionary<string, object>
{
["type"] = "IVA",
["rate"] = 0.16
}
}
}
}
},
["use"] = "G01",
["payment_form"] = "28" // "Tarjeta de débito"
}, new Dictionary<string, object>
{
["async"] = true
});
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(
"customer", Map.of(
"legal_name", "Dunder Mifflin",
"email", "email@example.com",
"tax_id", "ABC101010111",
"tax_system", "601",
"address", Map.of("zip", "85900")
),
"items", List.of(Map.of(
"quantity", 2,
"product", Map.of(
"description", "Ukelele",
"product_key", "60131324",
"price", 345.60,
"taxes", List.of(Map.of(
"type", "IVA",
"rate", 0.16
))
)
)),
"use", "G01",
"payment_form", "28"
),
Map.of("async", true)
);
$invoice = $facturapi->Invoices->create([
"customer" => [
"legal_name" => "Dunder Mifflin",
"email" => "email@example.com",
"tax_id" => "ABC101010111",
"tax_system" => "601",
"address" => [
"zip" => "85900"
]
],
"items" => [
[
"quantity" => 2,
"product" => [
"description" => "Ukelele",
"product_key" => "60131324",
"price" => 345.60,
"taxes" => [
[
"type" => "IVA",
"rate" => 0.16
]
]
]
]
],
"use" => "G01",
"payment_form" => "28" // "Tarjeta de débito"
], [
"async" => true
]);
curl https://www.facturapi.io/v2/invoices \
-H "Authorization Bearer sk_test_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"legal_name": "Dunder Mifflin",
"email": "email@example.com",
"tax_id": "ABC101010111",
"tax_system": "601",
"address": {
"zip": "85900"
}
},
"items": [
{
"quantity": 2,
"product": {
"description": "Ukelele",
"product_key": "60131324",
"price": 345.60,
"taxes": [
{
"type": "IVA",
"rate": 0.16
}
]
}
}
],
"use": "G01",
"payment_form": "28" // "Tarjeta de débito"
}'
Response
{
"id": "5f4b1b4b4b4b4b4b4b4b4b4a",
"created_at": "2020-08-29T00:00:00.000Z",
"status": "pending",
"customer": {
"id": "5f4b1b4b4b4b4b4b4b4b4b4b",
"legal_name": "Dunder Mifflin",
"email": "email@example.com",
"tax_id": "ABC101010111",
"tax_system": "601",
"address": {
"country": "MEX",
"zip": "85900"
}
},
"items": [
{
"quantity": 2,
"product": {
"description": "Ukelele",
"product_key": "60131324",
"price": 345.60,
"taxes": [
{
"type": "IVA",
"rate": 0.16
}
]
}
}
],
"use": "G01",
"payment_form": "28",
"stamp": null,
"uuid": null
}