Saltar al contenido principal

Backend FEL API - RPAfelApi cURL Commands

Complete cURL reference for all backend endpoints that use RPAfelApi.

Configuration

# Base URL (default: http://localhost:4000)
export BASE_URL="http://localhost:4000"

# Firebase ID Token (get from browser dev tools or Firebase CLI)
export TOKEN="YOUR_FIREBASE_ID_TOKEN"

# Example UUIDs - Replace with actual values from your database
export BUSINESS_ID="your-business-uuid"
export SALE_ID="your-certified-sale-uuid"
export USER_ID="your-user-uuid"
export LOCATION_ID="your-location-uuid"
export CUSTOMER_ID="your-customer-uuid"
export CURRENCY_ID="your-currency-uuid"

1. Certify Invoice Document (FACT)

POST /fel/certify-document

Certifies an invoice document via RPAfelApi. This endpoint automatically:

  • Converts Invoice to DTE JSON format
  • Retrieves FEL credentials from business config
  • Gets token from RPAfelApi (with caching)
  • Sends to RPAfelApi for certification
  • Handles retries and error cases

Basic Invoice

curl -X POST "${BASE_URL}/fel/certify-document" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"businessData": {
"id": "'"${BUSINESS_ID}"'"
},
"felProviderData": {
"providerName": "rpafelapi"
},
"invoiceNumber": "FAC-001",
"date": "2025-01-21",
"generalData": {
"type": "FACT",
"dateTimeIssue": "2025-01-21T10:00:00.000Z",
"currencyCode": "GTQ"
},
"issuerData": {
"taxId": "44653948",
"taxName": "LA LECHITA, SOCIEDAD ANONIMA",
"establishmentCode": "1",
"commercialName": "TUSA",
"vatAffiliationCode": "GEN",
"addressData": {
"address": "KM 55.5 CARRETERA INTERAMERICANA, CENTRO COMERCIAL ANDARIA LOCAL47 ZONA 4 CHIMALTENANGO, CHIMALTENANGO",
"postalCode": "04001",
"municipality": "Chimaltenango",
"department": "Chimaltenango",
"country": "GT"
}
},
"receiverData": {
"taxId": "CF",
"taxName": "CONSUMIDOR FINAL",
"addressData": {
"address": "CIUDAD",
"postalCode": "01010",
"municipality": "GUATEMALA",
"department": "GUATEMALA",
"country": "GT"
}
},
"phrases": [
{
"phraseType": "1",
"scenarioCode": "1"
}
],
"items": [
{
"name": "Product 1",
"unitOfMeasure": "UNI",
"goodOrService": "B",
"quantity": 2,
"unitPrice": 20.00,
"amount": 40.00,
"discount": 0.00,
"taxes": [
{
"shortName": "IVA",
"taxableUnitCode": "1",
"taxableAmount": 35.714285,
"taxAmount": 4.285714
}
]
}
],
"addendumData": {
"version": "7.1234654163",
"internalReference": "'"${SALE_ID}"'",
"dateReference": "2025-01-21T10:00:00.000Z",
"validateInternalReference": "VALIDAR"
},
"total": 40.00
}'

Invoice with Tip (Propina)

When an item has "PROPINA" or "TIP" in the name, the system automatically sets PropinaAdenda: "1":

curl -X POST "${BASE_URL}/fel/certify-document" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"businessData": {
"id": "'"${BUSINESS_ID}"'"
},
"felProviderData": {
"providerName": "rpafelapi"
},
"generalData": {
"type": "FACT",
"dateTimeIssue": "2025-01-21T10:00:00.000Z",
"currencyCode": "GTQ"
},
"issuerData": {
"taxId": "44653948",
"taxName": "RESTAURANT NAME, S.A.",
"establishmentCode": "1",
"commercialName": "RESTAURANT",
"vatAffiliationCode": "GEN",
"addressData": {
"address": "ADDRESS",
"postalCode": "01001",
"municipality": "Guatemala",
"department": "Guatemala",
"country": "GT"
}
},
"receiverData": {
"taxId": "49862952",
"taxName": "CUSTOMER NAME",
"taxpayerType": "NIT",
"addressData": {
"address": "ADDRESS",
"postalCode": "01001",
"municipality": "Guatemala",
"department": "Guatemala",
"country": "GT"
}
},
"phrases": [
{
"phraseType": "1",
"scenarioCode": "1"
}
],
"items": [
{
"name": "Meal",
"unitOfMeasure": "UNI",
"goodOrService": "S",
"quantity": 1,
"unitPrice": 100.00,
"amount": 100.00,
"discount": 0.00,
"taxes": [
{
"shortName": "IVA",
"taxableUnitCode": "1",
"taxableAmount": 89.29,
"taxAmount": 10.71
}
]
},
{
"name": "PROPINA",
"unitOfMeasure": "UNI",
"goodOrService": "S",
"quantity": 1,
"unitPrice": 10.00,
"amount": 10.00,
"discount": 0.00,
"taxes": []
}
],
"addendumData": {
"version": "7.1234654163",
"internalReference": "'"${SALE_ID}"'",
"dateReference": "2025-01-21T10:00:00.000Z",
"validateInternalReference": "VALIDAR"
},
"total": 110.00
}'

Note: The system automatically detects "PROPINA" in the item name and sets PropinaAdenda: "1" in the DTE JSON.

Invoice with CUI Identification

For customers identified by CUI instead of NIT:

curl -X POST "${BASE_URL}/fel/certify-document" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"businessData": {
"id": "'"${BUSINESS_ID}"'"
},
"felProviderData": {
"providerName": "rpafelapi"
},
"generalData": {
"type": "FACT",
"dateTimeIssue": "2025-01-21T10:00:00.000Z",
"currencyCode": "GTQ"
},
"issuerData": {
"taxId": "44653948",
"taxName": "COMPANY NAME, S.A.",
"establishmentCode": "1",
"commercialName": "COMPANY",
"vatAffiliationCode": "GEN",
"addressData": {
"address": "ADDRESS",
"postalCode": "01001",
"municipality": "Guatemala",
"department": "Guatemala",
"country": "GT"
}
},
"receiverData": {
"taxId": "2260269730101",
"taxName": "CUSTOMER NAME",
"taxpayerType": "CUI",
"addressData": {
"address": "ADDRESS",
"postalCode": "01001",
"municipality": "Guatemala",
"department": "Guatemala",
"country": "GT"
}
},
"phrases": [
{
"phraseType": "1",
"scenarioCode": "1"
}
],
"items": [
{
"name": "Product description",
"unitOfMeasure": "UNI",
"goodOrService": "B",
"quantity": 1,
"unitPrice": 100.00,
"amount": 100.00,
"discount": 0.00,
"taxes": [
{
"shortName": "IVA",
"taxableUnitCode": "1",
"taxableAmount": 89.29,
"taxAmount": 10.71
}
]
}
],
"addendumData": {
"version": "7.1234654163",
"internalReference": "'"${SALE_ID}"'",
"dateReference": "2025-01-21T10:00:00.000Z",
"validateInternalReference": "VALIDAR"
},
"total": 100.00
}'

Important:

  • For regular NITs, do NOT set taxpayerType or set it to null/undefined. The system will omit TipoEspecial automatically.
  • For CUI or other special identification types, set taxpayerType: "CUI" (or "EXT", etc.) and the system will automatically set TipoEspecial: "CUI" in the DTE JSON.
  • Never set taxpayerType: "NIT" - this causes validation errors because "NIT" is not a valid value for TipoEspecial.

Response Example

{
"Codigo": 0,
"Mensaje": "OK",
"AcuseReciboSAT": "A-1234567890",
"Autorizacion": "A-123456",
"Serie": "A",
"NUMERO": "123456",
"Fecha_DTE": "2025-01-21T10:00:00Z",
"Fecha_de_certificacion": "2025-01-21T10:00:00Z",
"NITCertificador": "12345678",
"NombreCertificador": "DIGIFACT S.A.",
"ResponseDATA1": "base64-xml-content"
}

2. Get Shared Info (NIT/CUI Lookup)

POST /fel/get-shared-info

Queries taxpayer information from RPAfelApi. This endpoint uses RPAfelApi's QueryPayerInfo endpoint.

Query by NIT

curl -X POST "${BASE_URL}/fel/get-shared-info" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"businessId": "'"${BUSINESS_ID}"'",
"data1": "SHARED_GETINFONITcom",
"data2": "NIT|49862952"
}'

Query by CUI

curl -X POST "${BASE_URL}/fel/get-shared-info" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"businessId": "'"${BUSINESS_ID}"'",
"data1": "SHARED_GETINFOCUI",
"data2": "CUI|2260269730101"
}'

Response Example

{
"Success": true,
"TaxPayerId": "49862952",
"TaxPayerName": "RANGEL,CASTRO,,KENNETH,ZAIDD",
"PersonalId": null
}

3. Create and Certify Credit Note (NCRE)

POST /fel/credit-notes

Creates a credit note (Nota de Crédito) that will be certified via RPAfelApi.

curl -X POST "${BASE_URL}/fel/credit-notes" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"businessId": "'"${BUSINESS_ID}"'",
"saleId": "'"${SALE_ID}"'",
"createdBy": "'"${USER_ID}"'",
"creditNoteDate": "2025-01-21T10:00:00.000Z",
"customerId": "'"${CUSTOMER_ID}"'",
"taxId": "49862952",
"taxName": "Cliente de Prueba",
"taxAddress": "Ciudad de Guatemala",
"locationId": "'"${LOCATION_ID}"'",
"locationName": "Tienda Principal",
"currencyId": "'"${CURRENCY_ID}"'",
"currencyCode": "GTQ",
"minorUnit": 2,
"exchangeRate": 1.0,
"currency": {
"id": "'"${CURRENCY_ID}"'",
"code": "GTQ",
"name": "Quetzal",
"symbol": "Q"
},
"totalAmount": 100.00,
"totalBaseAmount": 90.00,
"detail": {
"items": [
{
"productId": "product-uuid",
"productName": "Producto de Prueba",
"quantity": 1,
"unitPrice": 100.00,
"amount": 100.00,
"baseAmount": 90.00,
"taxes": [
{
"taxId": "tax-uuid",
"taxName": "IVA",
"rate": 0.12,
"amount": 10.00,
"baseAmount": 90.00
}
]
}
]
},
"paymentDetail": {},
"taxpayerType": "NIT",
"originalInvoiceUuid": "A-123456",
"adjustmentReason": "Devolución de mercancía",
"generateElectronicTaxDocument": true
}'

Response: Returns credit note object with id field.

Get Credit Note

curl -X GET "${BASE_URL}/fel/credit-notes/{credit-note-id}" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json"

Get Credit Notes by Sale

curl -X GET "${BASE_URL}/fel/credit-notes/sale/${SALE_ID}" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json"

Certify Credit Note

curl -X POST "${BASE_URL}/fel/credit-notes/{credit-note-id}/certify" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json"

Note: This endpoint:

  • Validates SAT requirements
  • Converts to DTE JSON (NCRE type)
  • Sends to RPAfelApi via generateCertificateToSign
  • Updates credit note with certification details
  • Triggers inventory reversal event

4. Create and Certify Debit Note (NDEB)

POST /fel/debit-notes

Creates a debit note (Nota de Débito) that will be certified via RPAfelApi.

curl -X POST "${BASE_URL}/fel/debit-notes" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"businessId": "'"${BUSINESS_ID}"'",
"saleId": "'"${SALE_ID}"'",
"createdBy": "'"${USER_ID}"'",
"debitNoteDate": "2025-01-21T10:00:00.000Z",
"customerId": "'"${CUSTOMER_ID}"'",
"taxId": "49862952",
"taxName": "Cliente de Prueba",
"taxAddress": "Ciudad de Guatemala",
"locationId": "'"${LOCATION_ID}"'",
"locationName": "Tienda Principal",
"currencyId": "'"${CURRENCY_ID}"'",
"currencyCode": "GTQ",
"minorUnit": 2,
"exchangeRate": 1.0,
"currency": {
"id": "'"${CURRENCY_ID}"'",
"code": "GTQ",
"name": "Quetzal",
"symbol": "Q"
},
"totalAmount": 50.00,
"totalBaseAmount": 45.00,
"detail": {
"items": [
{
"productId": "product-uuid",
"productName": "Producto de Prueba",
"quantity": 1,
"unitPrice": 50.00,
"amount": 50.00,
"baseAmount": 45.00,
"taxes": [
{
"taxId": "tax-uuid",
"taxName": "IVA",
"rate": 0.12,
"amount": 5.00,
"baseAmount": 45.00
}
]
}
]
},
"paymentDetail": {},
"taxpayerType": "NIT",
"originalInvoiceUuid": "A-123456",
"adjustmentReason": "Ajuste por error en facturación",
"generateElectronicTaxDocument": true
}'

Get Debit Note

curl -X GET "${BASE_URL}/fel/debit-notes/{debit-note-id}" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json"

Get Debit Notes by Sale

curl -X GET "${BASE_URL}/fel/debit-notes/sale/${SALE_ID}" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json"

Certify Debit Note

curl -X POST "${BASE_URL}/fel/debit-notes/{debit-note-id}/certify" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json"

Note: This endpoint:

  • Validates SAT requirements
  • Converts to DTE JSON (NDEB type)
  • Sends to RPAfelApi via generateCertificateToSign
  • Updates debit note with certification details

5. Request and Certify Cancellation (ANULACION)

POST /fel/cancellations

Requests cancellation of an invoice. This will be certified via RPAfelApi.

curl -X POST "${BASE_URL}/fel/cancellations" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"saleId": "'"${SALE_ID}"'",
"cancellationReason": "Error en la facturación",
"createdBy": "'"${USER_ID}"'"
}'

Response: Returns cancellation object with id field.

Important: Cancellation can only be requested for invoices in the same month they were issued (SAT requirement).

Get Cancellation

curl -X GET "${BASE_URL}/fel/cancellations/{cancellation-id}" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json"

Get Cancellations by Sale

curl -X GET "${BASE_URL}/fel/cancellations/sale/${SALE_ID}" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json"

Certify Cancellation

curl -X POST "${BASE_URL}/fel/cancellations/{cancellation-id}/certify" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json"

Note: This endpoint:

  • Validates SAT requirements (same-month cancellation)
  • Converts to DTE JSON (ANULACION type)
  • Sends to RPAfelApi via generateCertificateToSign
  • Updates cancellation with certification details
  • Updates sale status to CANCELLED
  • Triggers inventory reversal event

6. Convert Invoice to XML (Testing/Debugging)

POST /fel/convert-to-xml

Converts an Invoice document to XML format. Useful for testing and debugging.

curl -X POST "${BASE_URL}/fel/convert-to-xml" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"businessData": {
"id": "'"${BUSINESS_ID}"'"
},
"felProviderData": {
"providerName": "rpafelapi"
},
"generalData": {
"type": "FACT",
"dateTimeIssue": "2025-01-21T10:00:00.000Z",
"currencyCode": "GTQ"
},
"issuerData": {
"taxId": "44653948",
"taxName": "LA LECHITA, SOCIEDAD ANONIMA",
"establishmentCode": "1",
"commercialName": "TUSA",
"vatAffiliationCode": "GEN",
"addressData": {
"address": "KM 55.5 CARRETERA INTERAMERICANA",
"postalCode": "04001",
"municipality": "Chimaltenango",
"department": "Chimaltenango",
"country": "GT"
}
},
"receiverData": {
"taxId": "CF",
"taxName": "CONSUMIDOR FINAL",
"addressData": {
"address": "CIUDAD",
"postalCode": "01010",
"municipality": "GUATEMALA",
"department": "GUATEMALA",
"country": "GT"
}
},
"phrases": [
{
"phraseType": "1",
"scenarioCode": "1"
}
],
"items": [
{
"name": "Product 1",
"unitOfMeasure": "UNI",
"goodOrService": "B",
"quantity": 2,
"unitPrice": 20.00,
"amount": 40.00,
"discount": 0.00,
"taxes": [
{
"shortName": "IVA",
"taxableUnitCode": "1",
"taxableAmount": 35.714285,
"taxAmount": 4.285714
}
]
}
],
"addendumData": {
"version": "7.1234654163",
"internalReference": "'"${SALE_ID}"'",
"dateReference": "2025-01-21T10:00:00.000Z",
"validateInternalReference": "VALIDAR"
},
"total": 40.00
}'

Response: XML content (Content-Type: application/xml)


Complete Workflow Examples

Invoice Certification Flow

#!/bin/bash

# 1. Certify invoice
RESPONSE=$(curl -s -X POST "${BASE_URL}/fel/certify-document" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d @invoice.json)

# Extract authorization number
AUTORIZACION=$(echo "$RESPONSE" | jq -r '.Autorizacion')
echo "Invoice certified: $AUTORIZACION"

# 2. Query payer info
curl -X POST "${BASE_URL}/fel/get-shared-info" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"businessId": "'"${BUSINESS_ID}"'",
"data1": "SHARED_GETINFONITcom",
"data2": "NIT|49862952"
}'

Credit Note Flow

#!/bin/bash

# 1. Create credit note
CREDIT_NOTE_RESPONSE=$(curl -s -X POST "${BASE_URL}/fel/credit-notes" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d @credit-note.json)

CREDIT_NOTE_ID=$(echo "$CREDIT_NOTE_RESPONSE" | jq -r '.id')
echo "Credit note created: $CREDIT_NOTE_ID"

# 2. Get credit note
curl -X GET "${BASE_URL}/fel/credit-notes/${CREDIT_NOTE_ID}" \
-H "Authorization: Bearer ${TOKEN}"

# 3. Certify credit note
CERT_RESPONSE=$(curl -s -X POST "${BASE_URL}/fel/credit-notes/${CREDIT_NOTE_ID}/certify" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json")

AUTORIZACION=$(echo "$CERT_RESPONSE" | jq -r '.Autorizacion')
echo "Credit note certified: $AUTORIZACION"

Cancellation Flow

#!/bin/bash

# 1. Request cancellation
CANCELLATION_RESPONSE=$(curl -s -X POST "${BASE_URL}/fel/cancellations" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"saleId": "'"${SALE_ID}"'",
"cancellationReason": "Error en la facturación",
"createdBy": "'"${USER_ID}"'"
}')

CANCELLATION_ID=$(echo "$CANCELLATION_RESPONSE" | jq -r '.id')
echo "Cancellation requested: $CANCELLATION_ID"

# 2. Certify cancellation
CERT_RESPONSE=$(curl -s -X POST "${BASE_URL}/fel/cancellations/${CANCELLATION_ID}/certify" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json")

AUTORIZACION=$(echo "$CERT_RESPONSE" | jq -r '.Autorizacion')
echo "Cancellation certified: $AUTORIZACION"

Quick Reference Table

EndpointMethodUses RPAfelApiDescription
/fel/certify-documentPOST✅ YesCertify invoice (FACT)
/fel/get-shared-infoPOST✅ YesQuery NIT/CUI info
/fel/credit-notesPOST❌ No*Create credit note
/fel/credit-notes/:id/certifyPOST✅ YesCertify credit note (NCRE)
/fel/debit-notesPOST❌ No*Create debit note
/fel/debit-notes/:id/certifyPOST✅ YesCertify debit note (NDEB)
/fel/cancellationsPOST❌ No*Request cancellation
/fel/cancellations/:id/certifyPOST✅ YesCertify cancellation (ANULACION)
/fel/convert-to-xmlPOST❌ NoConvert to XML (testing)

* These endpoints create records in the database but don't call RPAfelApi until certification.


RPAfelApi Features Used

Automatic Features

  1. Token Caching: Tokens are automatically cached and refreshed
  2. Retry Logic: Automatic retry with exponential backoff on transient failures
  3. Tip Detection: Automatically detects "PROPINA" items and sets PropinaAdenda: "1"
  4. CUI Support: Automatically handles CUI identification via taxpayerType: "CUI"
  5. Special NIT Handling: Framework for special NIT phrase handling
  6. Error Handling: Enhanced error handling with detailed logging

RPAfelApi Endpoints Called

  • POST /api/fel/GetToken - Get authentication token (cached)
  • POST /api/fel/generateCertificateToSign - Certify documents
  • POST /api/fel/QueryPayerInfo - Query taxpayer information

Error Handling

Common HTTP Status Codes

  • 200 OK - Request successful
  • 400 Bad Request - Invalid request data
  • 401 Unauthorized - Invalid or missing token
  • 406 Not Acceptable - Document already signed (RPAfelApi handles automatically)
  • 500 Internal Server Error - Server error

Error Response Format

{
"statusCode": 400,
"message": "Error message description",
"error": "Bad Request"
}

Retry Behavior

The backend automatically retries on:

  • 401 Unauthorized (token refresh)
  • 406 Not Acceptable (already signed)
  • 5xx Server errors

Retries are not performed on:

  • 400 Bad Request (client error)
  • 403 Forbidden (authorization error)

Notes

  1. Authentication: All endpoints require Authorization: Bearer <token> header

  2. Business Config: FEL credentials are stored in business.felCertifierConfig

  3. Provider Selection: Set felProviderData.providerName: "rpafelapi" to use RPAfelApi

  4. UUID Format: Use actual UUIDs from your database

  5. Date Format: Use ISO 8601 format: 2025-01-21T10:00:00.000Z

  6. Currency: Use GTQ for Guatemalan Quetzal

  7. Document Types:

    • FACT - Invoice
    • NCRE - Credit Note
    • NDEB - Debit Note
    • ANULACION - Cancellation
  8. TipoEspecial Handling:

    • Do NOT set taxpayerType: "NIT" - this causes validation errors
    • For regular NITs, omit taxpayerType or set it to null
    • For special types (CUI, EXT, etc.), set taxpayerType: "CUI" (or appropriate value)
    • The system automatically includes TipoEspecial only for valid special types

Testing Tips

  1. Use jq for JSON parsing:

    echo "$RESPONSE" | jq '.'
  2. Save responses to files:

    curl ... > response.json
  3. Verbose output for debugging:

    curl -v -X POST ...
  4. Check HTTP status:

    curl -w "\nHTTP Status: %{http_code}\n" ...

Last Updated: 2025-01-21
Maintained By: FEL Team