Invoices

Create, approve, and submit FIRS-compliant invoices with IRN generation, QR codes, PDF downloads, and FIRS operations

Create, manage, and submit FIRS-compliant invoices. This is the core module of the Earnipay API — invoices flow through a status-based lifecycle from draft to FIRS submission, with optional approval workflows, QR code generation, PDF downloads, and direct FIRS operations. This page also covers standalone IRN generation, QR code generation, and FIRS invoice search.

Endpoints

Invoice Management

MethodEndpointDescription
POST/v1/invoicesCreate a new invoice
GET/v1/invoicesList invoices (paginated, filterable)
GET/v1/invoices/{id}Get invoice details
PATCH/v1/invoices/{id}Update an invoice (DRAFT only)
DELETE/v1/invoices/{id}Cancel an invoice
POST/v1/invoices/{id}/approveApprove an invoice
POST/v1/invoices/{id}/rejectReject an invoice

FIRS Compliance & Submission

MethodEndpointDescription
POST/v1/invoices/{id}/generate-qrGenerate FIRS QR code for an invoice
GET/v1/invoices/{id}/pdfDownload invoice as PDF
POST/v1/invoices/{id}/submit-to-appSubmit to FIRS via APP provider
POST/v1/invoices/validateValidate invoice data against FIRS schema

Standalone Utilities

MethodEndpointDescription
POST/v1/irn-generator/generateGenerate a FIRS-compliant IRN
POST/v1/qr-generator/generateGenerate a standalone encrypted QR code

FIRS Operations

MethodEndpointDescription
PATCH/v1/api/v1/businesses/{businessId}/app/invoices/{invoiceId}/payment-statusUpdate payment status in FIRS
GET/v1/api/v1/businesses/{businessId}/app/invoices/searchSearch invoices from FIRS
🔑

All endpoints on this page require authentication. See Authentication for details.


Invoice Lifecycle

Invoices move through a series of statuses from creation to FIRS submission. The exact flow depends on your business settings.

DRAFT → PENDING_APPROVAL → APPROVED → PENDING → SUBMITTED → FIRS_APPROVED
                                                            → FIRS_REJECTED
                                                            → PAID
                              ↓
                          CANCELLED
StatusDescription
DRAFTInitial state. Invoice can be edited or cancelled
PENDING_APPROVALWaiting for an OWNER or ADMIN to approve (when requireApproval is enabled)
APPROVEDApproved and ready for FIRS submission
PENDINGQueued for submission to FIRS
SUBMITTEDSent to FIRS via the APP provider, awaiting response
FIRS_APPROVEDFIRS accepted the invoice
FIRS_REJECTEDFIRS rejected the invoice — check the rejection reason
PAIDPayment received for this invoice
CANCELLEDInvoice cancelled — cannot be reactivated
💡

When requireApproval is disabled in business settings, invoices skip PENDING_APPROVAL and move directly from DRAFT to APPROVED. When autoSubmitToFirs is enabled, approved invoices are automatically submitted without calling the submit endpoint.

Invoice Types

TypeDescription
STANDARDRegular tax invoice for goods or services delivered
PROFORMAPre-sale invoice issued before delivery
CREDIT_NOTEAdjustment reducing the amount on a previous invoice
DEBIT_NOTEAdjustment increasing the amount on a previous invoice

Create an Invoice

Create a new invoice with line items. The invoice is created in DRAFT status, and an IRN (Invoice Reference Number) is auto-generated in the format {InvoiceNumber}-{ServiceID}-{YYYYMMDD}.

curl -X POST https://e-invoicing.earnipay.com/v1/invoices \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "businessId": "biz_xyz789",
    "customerId": "cus_def456",
    "invoiceType": "STANDARD",
    "issueDate": "2026-03-13",
    "dueDate": "2026-04-13",
    "items": [
      {
        "description": "Cloud Hosting - Standard Plan",
        "quantity": 3,
        "unitPrice": 75000,
        "taxPercent": 7.5,
        "discount": 0,
        "productCode": "prod_abc123",
        "unit": "month"
      },
      {
        "description": "Consulting Services",
        "quantity": 10,
        "unitPrice": 150000,
        "taxPercent": 5,
        "discount": 50000,
        "productCode": "prod_def456",
        "unit": "hour"
      }
    ],
    "paymentTerms": "Net 30",
    "paymentMethod": "BANK_TRANSFER",
    "paymentDetails": "pay_abc123",
    "notes": "Thank you for your business."
  }'

Invoice Parameters

ParameterTypeRequiredDescription
businessIdstringYesID of the business issuing the invoice
customerIdstringYesID of the customer being invoiced
invoiceTypestringYesOne of: STANDARD, PROFORMA, CREDIT_NOTE, DEBIT_NOTE
issueDatestringYesInvoice date (ISO 8601 format: YYYY-MM-DD)
dueDatestringYesPayment due date (ISO 8601 format: YYYY-MM-DD)
itemsarrayYesLine items (at least one required)
paymentTermsstringNoPayment terms description (e.g., "Net 30")
paymentMethodstringNoOne of: BANK_TRANSFER, MOBILE_MONEY, CASH, CREDIT_CARD, OTHER
paymentDetailsstringNoID of a saved payment detail
notesstringNoAdditional notes displayed on the invoice

Line Item Parameters

ParameterTypeRequiredDescription
descriptionstringYesLine item description
quantitynumberYesQuantity of units
unitPricenumberYesPrice per unit (in NGN)
taxPercentnumberYesTax percentage applied to this item
discountnumberNoDiscount amount in NGN (default: 0)
productCodestringNoID of a saved product
unitstringNoUnit of measurement (e.g., month, hour, piece)
{
  "statusCode": 201,
  "message": "Invoice created successfully.",
  "data": {
    "id": "inv_mno345",
    "businessId": "biz_xyz789",
    "customerId": "cus_def456",
    "invoiceType": "STANDARD",
    "status": "DRAFT",
    "irn": "INV-001-FIRS-SVC-001-20260313",
    "issueDate": "2026-03-13",
    "dueDate": "2026-04-13",
    "items": [
      {
        "description": "Cloud Hosting - Standard Plan",
        "quantity": 3,
        "unitPrice": 75000,
        "taxPercent": 7.5,
        "discount": 0,
        "lineTotal": 225000,
        "taxAmount": 16875,
        "unit": "month"
      },
      {
        "description": "Consulting Services",
        "quantity": 10,
        "unitPrice": 150000,
        "taxPercent": 5,
        "discount": 50000,
        "lineTotal": 1450000,
        "taxAmount": 72500,
        "unit": "hour"
      }
    ],
    "subtotal": 1675000,
    "totalTax": 89375,
    "totalDiscount": 50000,
    "total": 1764375,
    "paymentTerms": "Net 30",
    "paymentMethod": "BANK_TRANSFER",
    "notes": "Thank you for your business.",
    "createdAt": "2026-03-13T14:00:00.000Z",
    "updatedAt": "2026-03-13T14:00:00.000Z"
  }
}
How line item totals are calculated

Each line item total is calculated as:

lineTotal = (quantity × unitPrice) - discount
taxAmount = lineTotal × (taxPercent / 100)

Invoice totals aggregate all line items:

subtotal      = sum of all (quantity × unitPrice)
totalDiscount = sum of all discounts
totalTax      = sum of all taxAmounts
total         = subtotal - totalDiscount + totalTax

For the example above:

  • Item 1: (3 × ₦75,000) - ₦0 = ₦225,000 → tax: ₦16,875
  • Item 2: (10 × ₦150,000) - ₦50,000 = ₦1,450,000 → tax: ₦72,500
  • Total: ₦1,675,000 - ₦50,000 + ₦89,375 = ₦1,764,375

List Invoices

Retrieve a paginated list of invoices with filters for status, type, customer, and date range.

curl "https://e-invoicing.earnipay.com/v1/invoices?businessId=biz_xyz789&status=DRAFT&page=1&limit=10" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
ParameterTypeRequiredDescription
businessIdstringYesFilter by business ID
pageintegerNoPage number (default: 1)
limitintegerNoItems per page (default: 10)
searchstringNoSearch by IRN, customer name, or notes
statusstringNoFilter by status (e.g., DRAFT, APPROVED, FIRS_APPROVED)
invoiceTypestringNoFilter by type (e.g., STANDARD, CREDIT_NOTE)
customerIdstringNoFilter by customer ID
sortBystringNoField to sort by (e.g., issueDate, total, createdAt)
sortOrderstringNoasc or desc (default: desc)
startDatestringNoInvoices issued on or after this date (ISO 8601)
endDatestringNoInvoices issued on or before this date (ISO 8601)
{
  "statusCode": 200,
  "message": "Invoices retrieved successfully.",
  "data": {
    "items": [
      {
        "id": "inv_mno345",
        "invoiceType": "STANDARD",
        "status": "DRAFT",
        "irn": "INV-001-FIRS-SVC-001-20260313",
        "customerId": "cus_def456",
        "customerName": "Zenith Enterprises",
        "issueDate": "2026-03-13",
        "dueDate": "2026-04-13",
        "total": 1764375,
        "createdAt": "2026-03-13T14:00:00.000Z"
      }
    ],
    "meta": {
      "totalItems": 1,
      "itemCount": 1,
      "itemsPerPage": 10,
      "totalPages": 1,
      "currentPage": 1
    }
  }
}

Get Invoice Details

Retrieve the full details of an invoice, including all line items, payment information, and QR code data.

curl https://e-invoicing.earnipay.com/v1/invoices/inv_mno345 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
{
  "statusCode": 200,
  "message": "Invoice retrieved successfully.",
  "data": {
    "id": "inv_mno345",
    "businessId": "biz_xyz789",
    "customerId": "cus_def456",
    "customerName": "Zenith Enterprises",
    "invoiceType": "STANDARD",
    "status": "DRAFT",
    "irn": "INV-001-FIRS-SVC-001-20260313",
    "issueDate": "2026-03-13",
    "dueDate": "2026-04-13",
    "items": [
      {
        "description": "Cloud Hosting - Standard Plan",
        "quantity": 3,
        "unitPrice": 75000,
        "taxPercent": 7.5,
        "discount": 0,
        "lineTotal": 225000,
        "taxAmount": 16875,
        "unit": "month"
      },
      {
        "description": "Consulting Services",
        "quantity": 10,
        "unitPrice": 150000,
        "taxPercent": 5,
        "discount": 50000,
        "lineTotal": 1450000,
        "taxAmount": 72500,
        "unit": "hour"
      }
    ],
    "subtotal": 1675000,
    "totalTax": 89375,
    "totalDiscount": 50000,
    "total": 1764375,
    "paymentTerms": "Net 30",
    "paymentMethod": "BANK_TRANSFER",
    "notes": "Thank you for your business.",
    "qrCode": null,
    "createdAt": "2026-03-13T14:00:00.000Z",
    "updatedAt": "2026-03-13T14:00:00.000Z"
  }
}

Update an Invoice

Update an invoice that is still in DRAFT status. You can modify any field including line items. Invoices in any other status cannot be edited.

curl -X PATCH https://e-invoicing.earnipay.com/v1/invoices/inv_mno345 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "dueDate": "2026-05-13",
    "notes": "Payment terms extended to 60 days.",
    "items": [
      {
        "description": "Cloud Hosting - Standard Plan",
        "quantity": 6,
        "unitPrice": 75000,
        "taxPercent": 7.5,
        "discount": 0,
        "unit": "month"
      }
    ]
  }'
{
  "statusCode": 200,
  "message": "Invoice updated successfully.",
  "data": {
    "id": "inv_mno345",
    "status": "DRAFT",
    "irn": "INV-001-FIRS-SVC-001-20260313",
    "dueDate": "2026-05-13",
    "items": [
      {
        "description": "Cloud Hosting - Standard Plan",
        "quantity": 6,
        "unitPrice": 75000,
        "taxPercent": 7.5,
        "discount": 0,
        "lineTotal": 450000,
        "taxAmount": 33750,
        "unit": "month"
      }
    ],
    "subtotal": 450000,
    "totalTax": 33750,
    "totalDiscount": 0,
    "total": 483750,
    "notes": "Payment terms extended to 60 days.",
    "updatedAt": "2026-03-13T16:00:00.000Z"
  }
}
⚠️

Updating items replaces the entire line items array. Include all line items in the request, not just the ones you want to change.


Cancel an Invoice

Cancel an invoice. Cancelled invoices cannot be reactivated. Use this for invoices that were created in error or are no longer needed.

curl -X DELETE https://e-invoicing.earnipay.com/v1/invoices/inv_mno345 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
{
  "statusCode": 200,
  "message": "Invoice cancelled successfully.",
  "data": {
    "id": "inv_mno345",
    "status": "CANCELLED"
  }
}
⚠️

Cancellation is permanent. If you need to adjust an invoice that has already been submitted to FIRS, create a CREDIT_NOTE or DEBIT_NOTE instead of cancelling.


Approve an Invoice

Approve an invoice that is in PENDING_APPROVAL status. Only users with the OWNER or ADMIN role can approve invoices.

curl -X POST https://e-invoicing.earnipay.com/v1/invoices/inv_mno345/approve \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
{
  "statusCode": 200,
  "message": "Invoice approved successfully.",
  "data": {
    "id": "inv_mno345",
    "status": "APPROVED",
    "approvedBy": "usr_abc123",
    "approvedAt": "2026-03-13T17:00:00.000Z"
  }
}

If autoSubmitToFirs is enabled in your business settings, the invoice is automatically submitted to FIRS after approval.


Reject an Invoice

Reject an invoice that is in PENDING_APPROVAL status. The invoice returns to DRAFT status so the creator can edit and resubmit it. Only OWNER or ADMIN roles can reject invoices.

curl -X POST https://e-invoicing.earnipay.com/v1/invoices/inv_mno345/reject \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Incorrect unit price for consulting services. Please update to ₦120,000/hr."
  }'
ParameterTypeRequiredDescription
reasonstringNoExplanation for the rejection (visible to the invoice creator)
{
  "statusCode": 200,
  "message": "Invoice rejected successfully.",
  "data": {
    "id": "inv_mno345",
    "status": "DRAFT",
    "rejectedBy": "usr_abc123",
    "rejectedAt": "2026-03-13T17:15:00.000Z",
    "rejectionReason": "Incorrect unit price for consulting services. Please update to ₦120,000/hr."
  }
}

Generate QR Code

Generate a FIRS-compliant QR code for an invoice. The QR code is encrypted using the RSA public key from your FIRS crypto keys and meets FIRS requirements (Error Correction Level H, minimum 300×300px).

curl -X POST https://e-invoicing.earnipay.com/v1/invoices/inv_mno345/generate-qr \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
{
  "statusCode": 200,
  "message": "QR code generated successfully.",
  "data": {
    "qrCodeBase64": "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5f...",
    "qrCodeDataUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5f..."
  }
}
FieldDescription
qrCodeBase64Raw Base64-encoded PNG image of the QR code
qrCodeDataUrlData URL ready for embedding in HTML (<img src="...">)
⚠️

You must upload your FIRS crypto keys file before generating QR codes. See Businesses — Upload Crypto Keys.


Download PDF

Download the invoice as a PDF file with embedded QR code and all FIRS-required fields.

curl https://e-invoicing.earnipay.com/v1/invoices/inv_mno345/pdf \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  --output invoice-INV-001.pdf

The response returns the PDF file with Content-Type: application/pdf. Use the --output flag in curl (or equivalent in your HTTP client) to save it to a file.


Submit to FIRS

Submit an approved invoice to FIRS via your configured APP provider. The invoice must be in APPROVED status and the business must have a working APP provider connection.

curl -X POST https://e-invoicing.earnipay.com/v1/invoices/inv_mno345/submit-to-app \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
{
  "statusCode": 200,
  "message": "Invoice submitted to FIRS successfully.",
  "data": {
    "id": "inv_mno345",
    "status": "SUBMITTED",
    "submittedAt": "2026-03-13T18:00:00.000Z"
  }
}

After submission, the invoice status updates asynchronously based on the FIRS response:

  • FIRS_APPROVED — FIRS accepted the invoice
  • FIRS_REJECTED — FIRS rejected the invoice (check the rejection details on the invoice)

Validate Invoice Data

Validate invoice data against the FIRS schema without creating an invoice. Use this to check that your data is compliant before submission.

curl -X POST https://e-invoicing.earnipay.com/v1/invoices/validate \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "irn": "INV-001-FIRS-SVC-001-20260313",
    "issueDate": "2026-03-13",
    "invoiceType": "STANDARD",
    "supplier": {
      "name": "Okafor Trading International Ltd",
      "TIN": "12345678-0001",
      "address": "42 Victoria Island Blvd, Lagos"
    },
    "buyer": {
      "name": "Zenith Enterprises",
      "TIN": "98765432-0001",
      "address": "8 Broad Street, Lagos"
    },
    "items": [
      {
        "description": "Cloud Hosting - Standard Plan",
        "quantity": 3,
        "unitPrice": 75000,
        "taxPercent": 7.5
      }
    ],
    "taxTotal": 16875,
    "monetaryTotal": 241875
  }'
{
  "statusCode": 200,
  "message": "Invoice data is valid.",
  "data": {
    "isValid": true,
    "errors": []
  }
}

Generate IRN (Standalone)

Generate a FIRS-compliant Invoice Reference Number (IRN) outside the invoice creation flow. IRNs follow the format {InvoiceNumber}-{ServiceID}-{YYYYMMDD}. Use this when pre-assigning IRNs in bulk or integrating with external invoicing systems.

💡

When you create an invoice via POST /v1/invoices, an IRN is auto-generated. Use this standalone endpoint only when you need to generate IRNs independently.

curl -X POST https://e-invoicing.earnipay.com/v1/irn-generator/generate \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "invoiceNumber": "INV-001",
    "serviceId": "FIRS-SVC-001",
    "issueDate": "2026-03-13"
  }'
ParameterTypeRequiredDescription
invoiceNumberstringYesYour invoice number or reference
serviceIdstringYesFIRS Service ID from your business FIRS config
issueDatestringYesInvoice issue date (YYYY-MM-DD)
{
  "statusCode": 200,
  "message": "IRN generated successfully.",
  "data": {
    "irn": "INV-001-FIRS-SVC-001-20260313"
  }
}

IRN Format

ComponentDescriptionExample
InvoiceNumberSequential invoice number for your businessINV-001
ServiceIDYour FIRS-assigned Service IDFIRS-SVC-001
YYYYMMDDInvoice issue date in 8-digit format20260313

Generate QR Code (Standalone)

Generate an encrypted FIRS-compliant QR code outside the invoice flow. Use this when embedding QR codes in custom PDF templates or external systems. For invoice-level QR generation, see Generate QR Code above.

Prerequisites

  1. Configure FIRS settingsPATCH /v1/businesses/{id}/firs-config with your Business ID and Service ID. See Businesses — FIRS Configuration
  2. Upload crypto keysPATCH /v1/businesses/{id}/crypto-keys with the crypto_keys.txt file from FIRS. See Businesses — Upload Crypto Keys

FIRS QR Code Requirements

RequirementValue
EncryptionRSA using the FIRS-issued public key
Error Correction LevelH (High — 30% data recovery)
Minimum Size300 × 300 pixels
Output FormatPNG image (Base64-encoded)

Request

curl -X POST https://e-invoicing.earnipay.com/v1/qr-generator/generate \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "businessId": "biz_xyz789",
    "irn": "INV-001-FIRS-SVC-001-20260313",
    "issueDate": "2026-03-13",
    "invoiceType": "STANDARD",
    "supplierTIN": "12345678-0001",
    "buyerTIN": "98765432-0001",
    "totalAmount": 1764375,
    "taxAmount": 89375
  }'
ParameterTypeRequiredDescription
businessIdstringYesID of the business (must have crypto keys uploaded)
irnstringYesInvoice Reference Number
issueDatestringYesInvoice issue date (YYYY-MM-DD)
invoiceTypestringYesOne of: STANDARD, PROFORMA, CREDIT_NOTE, DEBIT_NOTE
supplierTINstringYesSupplier's Tax Identification Number
buyerTINstringYesBuyer's Tax Identification Number
totalAmountnumberYesInvoice total amount in NGN
taxAmountnumberYesTotal tax amount in NGN
{
  "statusCode": 200,
  "message": "QR code generated successfully.",
  "data": {
    "qrCodeBase64": "iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5f...",
    "qrCodeDataUrl": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5f..."
  }
}

Using the QR Code

Embed the QR code directly in a web page using the qrCodeDataUrl:

<img
  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5f..."
  alt="FIRS QR Code"
  width="300"
  height="300"
/>

Update Payment Status in FIRS

Update the payment status of an invoice in the FIRS system via your APP provider. Use this after receiving payment for an invoice that has been submitted to FIRS.

curl -X PATCH "https://e-invoicing.earnipay.com/v1/api/v1/businesses/biz_xyz789/app/invoices/inv_mno345/payment-status" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "status": "PAID",
    "paymentDate": "2026-04-10",
    "paymentReference": "TRF-20260410-001"
  }'
ParameterTypeRequiredDescription
statusstringYesPayment status (e.g., PAID)
paymentDatestringYesDate payment was received (YYYY-MM-DD)
paymentReferencestringNoPayment reference or transaction ID
{
  "statusCode": 200,
  "message": "Payment status updated in FIRS successfully.",
  "data": {
    "invoiceId": "inv_mno345",
    "status": "PAID",
    "paymentDate": "2026-04-10",
    "paymentReference": "TRF-20260410-001"
  }
}

Search Invoices from FIRS

Search for invoices directly from the FIRS system via your APP provider. Use this to verify invoice status, reconcile records, or retrieve invoices submitted by other parties.

curl "https://e-invoicing.earnipay.com/v1/api/v1/businesses/biz_xyz789/app/invoices/search?irn=INV-001-FIRS-SVC-001-20260313" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
ParameterTypeRequiredDescription
irnstringNoSearch by Invoice Reference Number
supplierTINstringNoSearch by supplier's TIN
buyerTINstringNoSearch by buyer's TIN
startDatestringNoInvoices issued on or after this date (YYYY-MM-DD)
endDatestringNoInvoices issued on or before this date (YYYY-MM-DD)
{
  "statusCode": 200,
  "message": "FIRS invoice search completed.",
  "data": {
    "items": [
      {
        "irn": "INV-001-FIRS-SVC-001-20260313",
        "invoiceType": "STANDARD",
        "supplierTIN": "12345678-0001",
        "buyerTIN": "98765432-0001",
        "issueDate": "2026-03-13",
        "totalAmount": 1764375,
        "taxAmount": 89375,
        "status": "FIRS_APPROVED"
      }
    ]
  }
}
⚠️

Both "Update Payment Status" and "Search Invoices from FIRS" require a configured and tested APP provider connection. See Businesses — APP Provider Configuration.


Error Handling

Status CodeErrorDescription
400Bad RequestMissing required fields, invalid parameters, or invoice not in required status
401UnauthorizedMissing or expired access token
403ForbiddenInsufficient role (e.g., only OWNER/ADMIN can approve)
404Not FoundInvoice ID doesn't exist
409ConflictInvoice is not in the correct status for this action
422Unprocessable EntityCrypto keys not uploaded (QR generation) or APP provider not configured (FIRS operations)
{
  "statusCode": 409,
  "message": "Invoice can only be updated in DRAFT status. Current status: APPROVED.",
  "error": "Conflict"
}
{
  "statusCode": 403,
  "message": "Only users with OWNER or ADMIN role can approve invoices.",
  "error": "Forbidden"
}