factsimil is, first and foremost, a REST API. The web panel you see on the modules page is just another client of that same API — if you're integrating electronic invoicing into a marketplace, a vertical ERP, or any platform of your own, here's what you need to get started.
This page covers the real receipt lifecycle. It isn't the complete reference for every endpoint (optional parameters, error codes, full SUNAT catalogs) — for that, write to us and we'll give you access to the full collection.
1. Authentication
Every authenticated request needs an Authorization: Bearer <token> header. The token is obtained with the same credentials as your account:
POST /api/auth/login
Content-Type: application/json
{ "email": "your-account@example.com", "password": "..." }
HTTP/1.1 200 OK
{ "token": "eyJhbGciOiJIUzI1NiIs...", "requiresMfa": false }That token is a short-lived JWT. Store it server-side on your platform — never in a mobile client or a public web client — and forward it on every call.
2. Create a receipt
A receipt starts as a draft. customerId and seriesId are the only fields that depend on data already created in your account (a customer and a series); the rest describes the receipt's line items:
POST /api/invoices
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type: application/json
{
"customerId": "3fa2...",
"seriesId": "9c1b...",
"moneda": "PEN",
"formaPago": "Contado",
"items": [
{
"descripcion": "Consulting services",
"cantidad": 1,
"precioUnitario": 250.00,
"tipoAfectacionIgv": "10"
}
]
}
HTTP/1.1 201 Created
{ "id": "6f1a...", "estado": "BORRADOR", "numero": null, "total": 295.00 }moneda accepts PEN, USD, EUR, GBP, CAD, JPY, SEK, or CHF. tipoAfectacionIgv follows SUNAT's Catálogo 07 (10 Taxable, 20 Exempt, 30 Not subject, 40 Export) — if you don't send it, it defaults to Taxable at the general IGV rate.
3. Sign and send to SUNAT
Signing is async: XML signing, sequential numbering, and transmission to SUNAT happen in a queue, not in the same request. You'll get a 202 with a jobId, not the final result:
POST /api/invoices/6f1a.../sign
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
HTTP/1.1 202 Accepted
{ "queued": true, "jobId": "42" }This is deliberate: sequential numbering has to resolve without race conditions even if two receipts are signed at the same instant, and SUNAT doesn't always respond instantly. That's why the next step is checking status, not assuming it's already done.
4. Check the status
There's no notification webhook yet — the real pattern is short polling on the same resource until estado stops being PROCESANDO:
GET /api/invoices/6f1a...
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
HTTP/1.1 200 OK
{
"id": "6f1a...",
"estado": "ACEPTADO",
"numero": 1042,
"hash": "8f3a2c...",
"xmlPath": "invoices/.../signed.xml",
"cdrPath": "invoices/.../cdr.zip"
}The real estado values you'll see are BORRADOR, PROCESANDO, ACEPTADO, OBSERVADO, and RECHAZADO — OBSERVADO means SUNAT accepted it with an observation (the receipt is valid), not that it failed.
5. XML, PDF, and shareable links
Once ACEPTADO or OBSERVADO, the signed XML and PDF are available directly:
GET /api/invoices/6f1a.../xml → application/xml (the signed XML, the same one SUNAT validates) GET /api/invoices/6f1a.../pdf → application/pdf
If your platform needs to send the receipt to the end customer without exposing your token, generate a single-resource shareable link:
POST /api/invoices/6f1a.../share-link
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
HTTP/1.1 201 Created
{ "url": "https://factsimil.com/api/public/invoices/<token>/pdf" }6. Multi-company: the x-tenant-id header
If your account has access to more than one company (for example, you're an accountant with several RUCs), every request operates on your primary company unless you explicitly send x-tenant-id: <company-id>. This lets you resolve, within the same token, which company you're acting on for each call — useful if your platform manages invoicing for several clients from a single integration.
7. Next steps
- Before issuing in production, your digital certificate needs to be uploaded — see the modules page for the full flow.
- Creating a free account gives you immediate access to the panel and the same credentials this API uses — there's no separate "sandbox mode" with different test data.
- Integrating this for more than one end customer (a marketplace, a vertical ERP)? Write to us — it's exactly the use case factsimil was designed for.