Documentation Index Fetch the complete documentation index at: https://docs-mx.taxo.ws/llms.txt
Use this file to discover all available pages before exploring further.
This guide will help you perform your first SAT invoice extraction using the Taxo API.
Before you start
You need:
A Taxo API key (get it here )
CIEC or FIEL credentials from a taxpayer
A tool to make HTTP requests (cURL, Postman, or code)
Step 1: Set up authentication
Store your API key securely:
export TAXO_API_KEY = "your_api_key_here"
Let’s extract received invoices from 2024 for a specific RFC:
curl -X POST "https://api.taxo.co/v1/extractions" \
-H "Authorization: Bearer $TAXO_API_KEY " \
-H "Content-Type: application/json" \
-d '{
"subject": {
"identifier": "ABC010101ABC",
"name": "Mi Empresa S.A. de C.V."
},
"credentials": {
"type": "CIEC",
"password": "'"$( echo -n 'my_sat_password' | base64 )"'"
},
"options": {
"informationType": "INVOICE",
"period": {
"from": "2024-01-01",
"to": "2024-12-31"
},
"direction": "RECEIVED"
}
}'
Expected response:
{
"publicId" : "JOB20250104123456789A" ,
"status" : "PENDING" ,
"createdAt" : "2025-01-04T12:34:56.789Z" ,
"subject" : {
"identification" : "ABC010101ABC" ,
"fullName" : "Mi Empresa S.A. de C.V." ,
"personType" : "MORAL"
},
"discoveryCount" : 0 ,
"completedCount" : 0 ,
"failedCount" : 0
}
Save the publicId - you’ll need it to check status and download documents.
Step 3: Monitor progress
Extraction is an asynchronous process. Check the status regularly:
# Replace JOB20250104123456789A with your publicId
curl -X GET "https://api.taxo.co/v1/extractions/JOB20250104123456789A" \
-H "Authorization: Bearer $TAXO_API_KEY "
Step 4: Download documents
Once the extraction is complete, you can download the documents:
# Download the first document in XML format
curl -X GET "https://api.taxo.co/v1/extractions/JOB20250104123456789A/documents/DOCUMENT_ID/download?type=XML" \
-H "Authorization: Bearer $TAXO_API_KEY " \
-o "factura.xml"
Complete example script
Here’s a complete script that performs the entire process:
complete-example.js
complete_example.py
const fetch = require ( 'node-fetch' );
const fs = require ( 'fs' );
const API_KEY = process . env . TAXO_API_KEY ;
const BASE_URL = 'https://api.taxo.co' ;
async function main () {
try {
console . log ( '🚀 Iniciando extracción de facturas...' );
// 1. Crear extracción
const extraction = await createExtraction ();
console . log ( `✅ Extracción creada: ${ extraction . publicId } ` );
// 2. Esperar a que complete
const result = await waitForCompletion ( extraction . publicId );
// 3. Descargar primeros 5 documentos
await downloadDocuments ( result , 5 );
console . log ( '🎉 ¡Proceso completado exitosamente!' );
} catch ( error ) {
console . error ( '❌ Error:' , error . message );
process . exit ( 1 );
}
}
async function createExtraction () {
const response = await fetch ( ` ${ BASE_URL } /v1/extractions` , {
method: 'POST' ,
headers: {
'Authorization' : `Bearer ${ API_KEY } ` ,
'Content-Type' : 'application/json'
},
body: JSON . stringify ({
subject: {
identifier: 'ABC010101ABC' , // Reemplaza con el RFC real
name: 'Mi Empresa S.A. de C.V.'
},
credentials: {
type: 'CIEC' ,
password: Buffer . from ( 'my_sat_password' ). toString ( 'base64' ) // Reemplaza
},
options: {
informationType: 'INVOICE' ,
period: {
from: '2024-01-01' ,
to: '2024-03-31' // Solo Q1 para el ejemplo
},
direction: 'RECEIVED'
}
})
});
if ( ! response . ok ) {
const error = await response . json ();
throw new Error ( `Error creando extracción: ${ error . error ?. message } ` );
}
return await response . json ();
}
async function waitForCompletion ( extractionId ) {
console . log ( '⏳ Esperando que se complete la extracción...' );
const delays = [ 5 , 10 , 20 , 30 , 60 ]; // Backoff exponencial
let delayIndex = 0 ;
while ( true ) {
const response = await fetch ( ` ${ BASE_URL } /v1/extractions/ ${ extractionId } ` , {
headers: { 'Authorization' : `Bearer ${ API_KEY } ` }
});
const status = await response . json ();
const progress = status . progress || {};
console . log ( ` Estado: ${ status . status } - Progreso: ${ progress . percentage || 0 } %` );
if ( status . status === 'COMPLETED' ) {
console . log ( `✅ ¡Completado! ${ progress . completedCount } documentos extraídos` );
return status ;
}
if ( status . status === 'FAILED' ) {
throw new Error ( `Extracción falló: ${ status . error ?. message } ` );
}
// Esperar con backoff exponencial
const delay = delays [ Math . min ( delayIndex ++ , delays . length - 1 )] * 1000 ;
await new Promise ( resolve => setTimeout ( resolve , delay ));
}
}
async function downloadDocuments ( extractionStatus , maxDocuments = 5 ) {
const documents = extractionStatus . documents . slice ( 0 , maxDocuments );
console . log ( `📥 Descargando ${ documents . length } documentos...` );
for ( let i = 0 ; i < documents . length ; i ++ ) {
const doc = documents [ i ];
const format = doc . availableFormats [ 0 ];
console . log ( ` Descargando ${ i + 1 } / ${ documents . length } : ${ doc . uuid } ` );
const response = await fetch (
` ${ BASE_URL } /v1/extractions/ ${ extractionStatus . publicId } /documents/ ${ doc . id } /download?type= ${ format } ` ,
{ headers: { 'Authorization' : `Bearer ${ API_KEY } ` } }
);
if ( ! response . ok ) {
console . warn ( ` ⚠️ Error descargando ${ doc . uuid } : ${ response . status } ` );
continue ;
}
const buffer = Buffer . from ( await response . arrayBuffer ());
const filename = `documento_ ${ i + 1 } _ ${ doc . uuid } . ${ format . toLowerCase () } ` ;
fs . writeFileSync ( filename , buffer );
console . log ( ` ✅ Guardado: ${ filename } ` );
}
}
// Ejecutar si es llamado directamente
if ( require . main === module ) {
main ();
}
Next steps
Congratulations! You now know how to use the basic Taxo API. You can now:
Set up webhooks Receive automatic notifications when extractions are ready
Explore endpoints Discover all advanced filtering and configuration options
Best practices Learn how to optimize performance and handle errors
Official SDKs Use our official libraries for your favorite language
Need help?
If you have problems following this guide, contact our support team: