Earnipay Invoices API
Invoice creation, management, and FIRS validation
Invoice creation, management, and FIRS validation
openapi: 3.0.0
info:
title: Earnipay Invoicing App Invoices API
description: FIRS-compliant e-invoicing platform API
version: '1.0'
contact: {}
servers: []
tags:
- name: Invoices
description: Invoice creation, management, and FIRS validation
paths:
/v1/invoices:
post:
description: Create a new invoice with line items. IRN is automatically generated.
operationId: InvoiceController_createInvoice_v1
parameters:
- name: businessId
required: true
in: query
description: Business ID
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateInvoiceDto'
responses:
'201':
description: Invoice created successfully
'400':
description: Bad Request - Invalid input or customer not found
'401':
description: Unauthorized
'403':
description: Forbidden - No access to this business
security:
- JWT-auth: []
summary: Create new invoice
tags:
- Invoices
get:
description: Retrieve paginated list of invoices with search, filter, and sort capabilities.
operationId: InvoiceController_getInvoices_v1
parameters:
- name: businessId
required: true
in: query
description: Business ID
schema:
type: string
- name: page
required: false
in: query
description: Page number
schema:
minimum: 1
default: 1
example: 1
type: number
- name: limit
required: false
in: query
description: Items per page
schema:
minimum: 1
maximum: 100
default: 20
example: 20
type: number
- name: search
required: false
in: query
description: Search query (searches in IRN, customer name)
schema:
example: INV001
type: string
- name: status
required: false
in: query
description: Filter by status
schema:
enum:
- DRAFT
- PENDING_APPROVAL
- APPROVED
- PENDING
- SUBMITTED
- FIRS_APPROVED
- FIRS_REJECTED
- PAID
- CANCELLED
type: string
- name: invoiceType
required: false
in: query
description: Filter by invoice type
schema:
enum:
- STANDARD
- PROFORMA
- CREDIT_NOTE
- DEBIT_NOTE
type: string
- name: customerId
required: false
in: query
description: Filter by customer ID
schema:
example: 123e4567-e89b-12d3-a456-426614174000
type: string
- name: dateFrom
required: false
in: query
description: Filter by issue date (from)
schema:
example: '2024-01-01'
type: string
- name: dateTo
required: false
in: query
description: Filter by issue date (to)
schema:
example: '2024-12-31'
type: string
- name: sortBy
required: false
in: query
description: Sort field
schema:
enum:
- irn
- issueDate
- dueDate
- total
- status
- createdAt
type: string
- name: sortOrder
required: false
in: query
description: Sort order
schema:
enum:
- asc
- desc
type: string
responses:
'200':
description: Invoices retrieved successfully
'401':
description: Unauthorized
'403':
description: Forbidden - No access to this business
security:
- JWT-auth: []
summary: Get invoices list
tags:
- Invoices
/v1/invoices/{id}/approve:
post:
description: Approve a PENDING_APPROVAL invoice. Only OWNER and ADMIN can approve.
operationId: InvoiceController_approveInvoice_v1
parameters:
- name: id
required: true
in: path
description: Invoice ID
schema:
type: string
- name: businessId
required: true
in: query
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ApproveInvoiceDto'
responses:
'200':
description: Invoice approved successfully
'400':
description: Invoice not in PENDING_APPROVAL status
'403':
description: Forbidden - Insufficient permissions
'404':
description: Invoice not found
security:
- JWT-auth: []
summary: Approve invoice
tags:
- Invoices
/v1/invoices/{id}/reject:
post:
description: Reject a PENDING_APPROVAL invoice. Only OWNER and ADMIN can reject. Invoice returns to DRAFT.
operationId: InvoiceController_rejectInvoice_v1
parameters:
- name: id
required: true
in: path
description: Invoice ID
schema:
type: string
- name: businessId
required: true
in: query
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RejectInvoiceDto'
responses:
'200':
description: Invoice rejected successfully
'400':
description: Invoice not in PENDING_APPROVAL status
'403':
description: Forbidden - Insufficient permissions
'404':
description: Invoice not found
security:
- JWT-auth: []
summary: Reject invoice
tags:
- Invoices
/v1/invoices/{id}:
get:
description: Retrieve detailed information about a specific invoice including all line items.
operationId: InvoiceController_getInvoiceById_v1
parameters:
- name: id
required: true
in: path
description: Invoice ID
schema:
type: string
responses:
'200':
description: Invoice details retrieved successfully
'401':
description: Unauthorized
'403':
description: Forbidden - No access to this invoice's business
'404':
description: Invoice not found
security:
- JWT-auth: []
summary: Get invoice details
tags:
- Invoices
patch:
description: Update invoice information. Only DRAFT invoices can be updated.
operationId: InvoiceController_updateInvoice_v1
parameters:
- name: id
required: true
in: path
description: Invoice ID
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateInvoiceDto'
responses:
'200':
description: Invoice updated successfully
'400':
description: Bad Request - Invalid input or invoice cannot be updated
'401':
description: Unauthorized
'403':
description: Forbidden - No access to this invoice's business
'404':
description: Invoice not found
security:
- JWT-auth: []
summary: Update invoice
tags:
- Invoices
delete:
description: Cancel an invoice. Cannot cancel submitted or approved invoices.
operationId: InvoiceController_cancelInvoice_v1
parameters:
- name: id
required: true
in: path
description: Invoice ID
schema:
type: string
responses:
'200':
description: Invoice cancelled successfully
'400':
description: Bad Request - Invoice cannot be cancelled
'401':
description: Unauthorized
'403':
description: Forbidden - No access to this invoice's business
'404':
description: Invoice not found
security:
- JWT-auth: []
summary: Cancel invoice
tags:
- Invoices
/v1/invoices/{id}/generate-qr:
post:
description: Generate FIRS-compliant QR code for the invoice. Requires business FIRS configuration.
operationId: InvoiceController_generateQrCode_v1
parameters:
- name: id
required: true
in: path
description: Invoice ID
schema:
type: string
responses:
'200':
description: QR code generated successfully
'400':
description: Bad Request - FIRS crypto keys not configured
'401':
description: Unauthorized
'403':
description: Forbidden - No access to this invoice's business
'404':
description: Invoice not found
security:
- JWT-auth: []
summary: Generate QR code
tags:
- Invoices
/v1/invoices/{id}/pdf:
get:
description: Download invoice as PDF file. QR code will be included if generated.
operationId: InvoiceController_downloadPdf_v1
parameters:
- name: id
required: true
in: path
description: Invoice ID
schema:
type: string
responses:
'200':
description: PDF file downloaded successfully
headers:
Content-Type:
description: application/pdf
Content-Disposition:
description: attachment; filename="invoice-{IRN}.pdf"
'401':
description: Unauthorized
'403':
description: Forbidden - No access to this invoice's business
'404':
description: Invoice not found
security:
- JWT-auth: []
summary: Download invoice PDF
tags:
- Invoices
/v1/invoices/{id}/submit-to-app:
post:
description: Submit an APPROVED invoice to the APP provider (FIRS).
operationId: InvoiceController_submitToApp_v1
parameters:
- name: id
required: true
in: path
description: Invoice ID
schema:
type: string
responses:
'200':
description: Invoice submitted successfully
'400':
description: Invoice not in APPROVED status
'404':
description: Invoice not found
security:
- JWT-auth: []
summary: Submit invoice to APP provider
tags:
- Invoices
/v1/invoices/validate:
post:
description: 'Validate invoice data structure without creating an invoice.
This endpoint checks if your invoice data matches the FIRS requirements:
- Required fields presence
- IRN format validation
- Party information completeness (supplier & customer)
- Line items structure
- Tax totals validation
- Legal monetary totals calculations
Use this before submitting invoices to FIRS to catch validation errors early.'
operationId: InvoiceController_validateInvoiceData_v1
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ValidateInvoiceDataDto'
responses:
'200':
description: Validation completed (check the response for validation results)
content:
application/json:
schema:
$ref: '#/components/schemas/ValidateInvoiceResponse'
'401':
description: Unauthorized
security:
- JWT-auth: []
summary: Validate invoice data against FIRS schema
tags:
- Invoices
components:
schemas:
ApproveInvoiceDto:
type: object
properties:
comments:
type: string
description: Optional comments for the approval
example: Looks good, approved.
CreateInvoiceDto:
type: object
properties:
invoiceType:
type: string
description: Invoice type
example: STANDARD
enum:
- STANDARD
- PROFORMA
- CREDIT_NOTE
- DEBIT_NOTE
default: STANDARD
customerId:
type: string
description: Customer ID
example: 123e4567-e89b-12d3-a456-426614174000
issueDate:
type: string
description: Invoice issue date (ISO 8601)
example: '2025-10-25T00:00:00.000Z'
dueDate:
type: string
description: Invoice due date (ISO 8601)
example: '2025-11-01T00:00:00.000Z'
items:
description: Invoice items (line items)
minItems: 1
type: array
items:
$ref: '#/components/schemas/InvoiceItemDto'
paymentTerms:
type: string
description: Payment terms
example: Payment due within 7 days
paymentMethod:
type: string
description: Payment method
example: Bank Transfer
enum:
- Bank Transfer
- Cash
- Credit Card
- Mobile Money
- Other
paymentDetails:
type: string
description: Payment details (JSON string with account info). Ignored if paymentDetailId is provided.
example: '{"accountName":"John Doe Enterprises","accountNumber":"09090828929","bankName":"Access Bank"}'
paymentDetailId:
type: string
description: ID of a saved PaymentDetail to use. Overrides paymentDetails field.
example: 123e4567-e89b-12d3-a456-426614174000
notes:
type: string
description: Additional notes for the customer
example: Thank you for your business
internalNotes:
type: string
description: Internal notes (not visible to customer)
example: Rush order - deliver before Nov 1st
required:
- customerId
- issueDate
- items
UpdateInvoiceDto:
type: object
properties:
customerId:
type: string
description: Customer ID
example: 123e4567-e89b-12d3-a456-426614174000
issueDate:
type: string
description: Invoice issue date (ISO 8601)
example: '2025-10-25T00:00:00.000Z'
dueDate:
type: string
description: Invoice due date (ISO 8601)
example: '2025-11-01T00:00:00.000Z'
items:
description: Invoice items (replaces all existing items)
minItems: 1
type: array
items:
$ref: '#/components/schemas/InvoiceItemDto'
paymentTerms:
type: string
description: Payment terms
example: Payment due within 7 days
paymentMethod:
type: string
description: Payment method
example: Bank Transfer
paymentDetails:
type: string
description: Payment details (JSON string)
example: '{"accountName":"John Doe Enterprises","accountNumber":"09090828929","bankName":"Access Bank"}'
notes:
type: string
description: Additional notes
example: Thank you for your business
internalNotes:
type: string
description: Internal notes
example: Rush order
ValidateInvoiceDataDto:
type: object
properties:
irn:
type: string
description: Invoice Reference Number (IRN)
example: INV0001-94ND90NR-20240611
issue_date:
type: string
description: Invoice issue date (ISO format YYYY-MM-DD)
example: '2024-06-11'
invoice_type_code:
type: string
description: Invoice type code (e.g., 380 = Commercial invoice, 381 = Credit note)
example: '380'
document_currency_code:
type: string
description: Document currency code
example: NGN
tax_currency_code:
type: string
description: Tax currency code
example: NGN
accounting_supplier_party:
type: object
description: Supplier/seller information
example:
party_name: ABC Company Ltd
tin: 12345678-0001
email: contact@abc.com
telephone: '+2348012345678'
postal_address:
street_name: 123 Main Street
city_name: Lagos
country: NG
accounting_customer_party:
type: object
description: Customer/buyer information
example:
party_name: XYZ Company Ltd
tin: 87654321-0001
email: contact@xyz.com
telephone: '+2348087654321'
postal_address:
street_name: 456 Second Avenue
city_name: Abuja
country: NG
invoice_line:
type: array
description: Invoice line items
example:
- invoiced_quantity: 10
line_extension_amount: 10000
item:
name: Product ABC
description: Product description
price:
price_amount: 1000
base_quantity: 1
legal_monetary_total:
type: object
description: Legal monetary totals
example:
line_extension_amount: 10000
tax_exclusive_amount: 10000
tax_inclusive_amount: 10750
payable_amount: 10750
tax_total:
type: array
description: Tax totals (array)
example:
- tax_amount: 750
tax_subtotal:
- taxable_amount: 10000
tax_amount: 750
tax_category:
id: S
percent: 7.5
due_date:
type: string
description: Invoice due date (ISO format YYYY-MM-DD)
example: '2024-07-11'
note:
type: string
description: Invoice notes
example: 'Payment terms: Net 30'
required:
- irn
- issue_date
- invoice_type_code
- document_currency_code
- tax_currency_code
- accounting_supplier_party
- accounting_customer_party
- invoice_line
- legal_monetary_total
- tax_total
ValidateInvoiceResponse:
type: object
properties:
valid:
type: boolean
description: Whether the invoice data is valid according to FIRS schema
example: true
errors:
description: List of validation errors (empty if valid)
example: []
type: array
items:
type: string
warnings:
description: List of warnings for non-critical issues
example:
- TIN format should follow XX-XXXX-XXXX pattern
type: array
items:
type: string
details:
type: object
description: Detailed validation breakdown
example:
hasRequiredFields: true
hasValidIRN: true
hasValidParties: true
hasValidLineItems: true
hasValidTotals: true
hasValidTaxTotal: true
summary:
type: object
description: Summary of what was validated
example:
totalLineItems: 1
totalAmount: 10750
currencyCode: NGN
required:
- valid
- errors
- warnings
- details
RejectInvoiceDto:
type: object
properties:
reason:
type: string
description: Reason for rejection
example: Incorrect pricing on line item 2
comments:
type: string
description: Additional comments
required:
- reason
InvoiceItemDto:
type: object
properties:
description:
type: string
description: Item description
example: Bags of sugar
quantity:
type: number
description: Quantity
example: 10
minimum: 0.01
unitPrice:
type: number
description: Unit price
example: 30000
minimum: 0
taxPercent:
type: number
description: Tax percentage
example: 7.5
minimum: 0
maximum: 100
discount:
type: number
description: Discount amount
example: 0
default: 0
minimum: 0
productCode:
type: string
description: Product/Service code
example: PROD-001
unit:
type: string
description: Unit of measurement
example: bags
default: unit
required:
- description
- quantity
- unitPrice
- taxPercent
securitySchemes:
JWT-auth:
scheme: bearer
bearerFormat: JWT
type: http
name: JWT
description: Enter JWT token
in: header
API-Key:
type: apiKey
in: header
name: X-API-Key
description: API Key for third-party integrations