Skip to main content

FEL Backend API - cURL Test Examples

This document provides cURL commands for testing the FEL Backend API endpoints for Credit Notes, Debit Notes, and Cancellations.

Prerequisites

  1. Backend Server: Ensure the backend is running (default: http://localhost:4000)
  2. Authentication Token: Get a Firebase ID token from:
    • Browser DevTools: Application > Cookies > firebase-id-token
    • Or use Firebase CLI: firebase auth:export
    • Or extract from your frontend application's authentication state
  3. Valid UUIDs: You'll need valid UUIDs from your database:
    • Business ID
    • Sale ID (certified invoice)
    • User ID
    • Location ID
    • Customer ID
    • Currency ID
    • Original Invoice UUID (FEL UUID from sale.felNumber or sale.felUuid)

Base Configuration

Set these variables before running commands:

export BASE_URL="http://localhost:4000"
export TOKEN="YOUR_FIREBASE_ID_TOKEN_HERE"
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"
export ORIGINAL_INVOICE_UUID="fel-uuid-from-certified-sale"

Credit Note Endpoints

1. Create Credit Note

POST /fel/credit-notes

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": "2024-01-15T10:00:00.000Z",
"customerId": "'"${CUSTOMER_ID}"'",
"taxId": "12345678-9",
"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": "'"${ORIGINAL_INVOICE_UUID}"'",
"adjustmentReason": "Devolución de mercancía",
"generateElectronicTaxDocument": true
}'

Response: Returns the created credit note object with id field.

2. Get Credit Note by ID

GET /fel/credit-notes/:id

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

3. Get Credit Notes by Sale ID

GET /fel/credit-notes/sale/:saleId

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

Response: Returns an array of credit notes for the given sale.

4. Certify Credit Note

POST /fel/credit-notes/:id/certify

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

Note: This endpoint will:

  • Validate the credit note meets SAT requirements
  • Convert it to DTE JSON format
  • Send it to RPAfelApi for certification
  • Update the credit note with certification details
  • Trigger inventory reversal via event handler

Debit Note Endpoints

1. Create Debit Note

POST /fel/debit-notes

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": "2024-01-15T10:00:00.000Z",
"customerId": "'"${CUSTOMER_ID}"'",
"taxId": "12345678-9",
"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": "'"${ORIGINAL_INVOICE_UUID}"'",
"adjustmentReason": "Ajuste por error en facturación",
"generateElectronicTaxDocument": true
}'

2. Get Debit Note by ID

GET /fel/debit-notes/:id

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

3. Get Debit Notes by Sale ID

GET /fel/debit-notes/sale/:saleId

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

4. Certify Debit Note

POST /fel/debit-notes/:id/certify

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

Cancellation Endpoints

1. Request Cancellation

POST /fel/cancellations

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 the created cancellation object with id field.

Note: The cancellation reason must follow SAT requirements (e.g., same-month cancellation only).

2. Get Cancellation by ID

GET /fel/cancellations/:id

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

3. Get Cancellations by Sale ID

GET /fel/cancellations/sale/:saleId

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

Response: Returns an array of cancellations for the given sale.

4. Certify Cancellation

POST /fel/cancellations/:id/certify

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

Note: This endpoint will:

  • Validate the cancellation meets SAT requirements
  • Convert it to DTE JSON format
  • Send it to RPAfelApi for certification
  • Update the cancellation with certification details
  • Update the sale status to CANCELLED
  • Trigger inventory reversal via event handler

Testing Workflow

Complete Credit Note Flow

  1. Create Credit Note → Get creditNoteId
  2. Get Credit Note → Verify it was created correctly
  3. Certify Credit Note → Verify certification and inventory reversal

Complete Debit Note Flow

  1. Create Debit Note → Get debitNoteId
  2. Get Debit Note → Verify it was created correctly
  3. Certify Debit Note → Verify certification

Complete Cancellation Flow

  1. Request Cancellation → Get cancellationId
  2. Get Cancellation → Verify it was created correctly
  3. Certify Cancellation → Verify certification, sale status update, and inventory reversal

Common Validation Errors

Credit Note / Debit Note

  • Original Invoice UUID not found: Ensure the sale has been certified and has a valid FEL UUID
  • Credit note amount exceeds original: Credit note total cannot exceed original invoice total
  • Adjustment reason required: Must provide a valid SAT adjustment reason

Cancellation

  • Cancellation outside same month: Can only cancel invoices in the same month they were issued
  • Sale already cancelled: Cannot cancel an already cancelled sale
  • Cancellation reason required: Must provide a valid SAT cancellation reason

Getting Required Data from Database

Get a Certified Sale (Invoice)

# Query your database for a certified sale
# Look for: sale.status = 'certified' AND sale.felNumber IS NOT NULL
# Extract: id, felNumber (originalInvoiceUuid), businessId, etc.

Get Original Invoice UUID

The originalInvoiceUuid should be the FEL UUID from the certified sale:

  • Check sale.felNumber field (this is typically the FEL UUID)
  • Or check sale.felUuid if that field exists

Example: Using jq to Extract IDs

If you have jq installed, you can extract IDs from responses:

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

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

# Now use it to certify
curl -X POST "${BASE_URL}/fel/credit-notes/${CREDIT_NOTE_ID}/certify" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json"

Using the Test Script

A bash script is available at docs/fel/backend-api-test-curl-commands.sh:

# Make it executable
chmod +x docs/fel/backend-api-test-curl-commands.sh

# Edit the script to set your variables
# Then run it
./docs/fel/backend-api-test-curl-commands.sh

Troubleshooting

401 Unauthorized

  • Check that your Firebase ID token is valid and not expired
  • Verify the token is being sent correctly in the Authorization header

404 Not Found

  • Ensure the backend server is running
  • Check that the endpoint path is correct (/fel/...)

400 Bad Request

  • Check that all required fields are present in the request body
  • Verify UUID formats are correct
  • Check that the sale exists and is certified (for credit/debit notes)

500 Internal Server Error

  • Check backend logs for detailed error messages
  • Verify database connections and that migrations have been run
  • Ensure RPAfelApi credentials are configured if testing certification