EnvoyX Docs
Invoices

Invoices

Invoices

The Invoices API lets you upload PDF invoices, track their processing status, view extracted data, and manage invoice lifecycle.

Endpoints

MethodPathDescription
POST/api/v1/invoices/uploadUpload an invoice (PDF, max 10MB)
GET/api/v1/invoicesList invoices with pagination and filtering
GET/api/v1/invoices/{id}Get invoice detail with extracted data
DELETE/api/v1/invoices/{id}Delete an invoice
PATCH/api/v1/invoices/{id}/statusUpdate invoice status

All endpoints require the X-API-Key header.

Upload Invoice

Upload a PDF file for AI-powered extraction.

curl -X POST https://api.tryenvoyx.com/api/v1/invoices/upload \
  -H "X-API-Key: YOUR_API_KEY" \
  -F "file=@invoice.pdf"

Constraints:

  • File type: PDF only
  • Max file size: 10MB

Response:

{
  "success": true,
  "status": 201,
  "code": "INVOICE_UPLOADED",
  "message": "Invoice uploaded successfully",
  "data": {
    "id": "clx1234567890",
    "file_name": "invoice.pdf",
    "file_size": 245678,
    "status": "PENDING",
    "uploaded_at": "2024-02-10T12:00:00Z"
  }
}

After upload, the invoice enters the processing pipeline automatically. Use webhooks or WebSockets to get notified when processing completes.

List Invoices

Retrieve a paginated list of invoices with optional status filtering.

curl -X GET "https://api.tryenvoyx.com/api/v1/invoices?page=1&page_size=20&status_filter=PROCESSED" \
  -H "X-API-Key: YOUR_API_KEY"

Query Parameters:

ParameterTypeDefaultDescription
pageinteger1Page number
page_sizeinteger20Items per page
status_filterstringFilter by status (e.g., PROCESSED, FLAGGED, PENDING)

Response:

{
  "success": true,
  "status": 200,
  "code": "INVOICES_FETCHED",
  "message": "Invoices retrieved successfully",
  "data": {
    "invoices": [
      {
        "id": "clx1234567890",
        "file_name": "invoice.pdf",
        "status": "PROCESSED",
        "uploaded_at": "2024-02-10T12:00:00Z",
        "processed_at": "2024-02-10T12:00:18Z"
      }
    ],
    "total": 42,
    "page": 1,
    "page_size": 20
  }
}

Get Invoice Detail

Retrieve a single invoice with full extracted data.

curl -X GET https://api.tryenvoyx.com/api/v1/invoices/{id} \
  -H "X-API-Key: YOUR_API_KEY"

Response:

{
  "success": true,
  "status": 200,
  "code": "INVOICE_FETCHED",
  "message": "Invoice retrieved successfully",
  "data": {
    "invoice": {
      "id": "abc7b088-6739-485d-9371-fd3cd27d7dfb",
      "filename": "a1b2c3d4_invoice.pdf",
      "original_name": "invoice.pdf",
      "file_type": "application/pdf",
      "file_size": 245678,
      "status": "PROCESSED",
      "extraction_success": true,
      "extraction_processing_time": 18.52,
      "created_at": "2026-02-15T12:00:00Z",
      "updated_at": "2026-02-15T12:00:18Z",
      "download_url": "https://storage.example.com/invoice.pdf?signed=...",

      "claim_number": "CLM-2024-001",
      "insured_id": "INS-123456",
      "insurance_name": "Ascoma",
      "patient_name": "John Doe",
      "invoice_number": "INV-2024-0042",
      "submission_date": "2024-02-08",
      "insurance_value": "250000",
      "max_coverage": "500000",
      "out_of_pocket": "50000",

      "currency": "XOF",
      "total_amount": "300000",
      "insurance_percent": "83.33",
      "identified_insurer": "Ascoma",
      "provider_name": "Dr. Smith Clinic",

      "category_check": "PASS",
      "amount_check": "PASS",
      "partner_check": "PASS",
      "duplicate_check": "PASS",
      "submission_date_check": "PASS",

      "risk_score": 0,
      "risk_level": "LOW",

      "extraction_data": {
        "claim_number": "CLM-2024-001",
        "insured_id": "INS-123456",
        "insurance_name": "Ascoma",
        "identified_insurer": "Ascoma",
        "patient_name": "John Doe",
        "invoice_number": "INV-2024-0042",
        "submission_date": "2024-02-08",
        "insurance_amount": "250000",
        "out_of_pocket": "50000",
        "max_coverage": "500000",
        "provider_name": "Dr. Smith Clinic",
        "currency": "XOF",
        "total_amount": "300000",
        "insurance_percent": "83.33",
        "category_check": "PASS",
        "amount_check": "PASS",
        "partner_check": "PASS",
        "duplicate_check": "PASS",
        "submission_date_check": "PASS",
        "risk_score": 0,
        "risk_level": "LOW",
        "final_status": "VERIFIED",
        "validation_passed": true,
        "validation_flags": [],
        "summary_text": "Invoice summary...",
        "_extraction_quality": {
          "completeness_percentage": 90.0,
          "fields_extracted": 9,
          "total_fields": 10
        }
      }
    }
  }
}

Extracted Data Fields

Core Fields

FieldTypeDescription
claim_numberstringInsurance claim number
insured_idstringInsured person's ID
insurance_namestringInsurance company name
patient_namestringPatient's full name
invoice_numberstringInvoice reference number
submission_datestringDate invoice was submitted (ISO format)
insurance_amountstringAmount covered by insurance
insurance_valuestringAmount covered by insurance (alias)
max_coveragestringMaximum coverage amount
out_of_pocketstringPatient's out-of-pocket cost
provider_namestringService provider name

Additional Extraction Fields

FieldTypeDescription
currencystringISO currency code (e.g., XOF, USD, EUR)
total_amountstringTotal invoice amount (insurance + out of pocket)
insurance_percentstringPercentage covered by insurance (e.g., "83.33")
identified_insurerstringAI-identified insurance company name

Verification Checks

Each check returns "PASS" or "FAIL":

FieldTypeDescription
category_checkstringCategory verification result
amount_checkstringAmount verification result
partner_checkstringPartner verification result
duplicate_checkstringDuplicate detection result
submission_date_checkstringDate verification result

Risk Assessment

FieldTypeDescription
risk_scoreintegerComputed risk score
risk_levelstringRisk level: LOW, MEDIUM, or HIGH
final_statusstringFinal determination: VERIFIED or FLAGGED
validation_passedbooleanWhether all validation checks passed
validation_flagsarrayList of failed check names (empty if all passed)

Delete Invoice

Permanently delete an invoice and its extracted data.

curl -X DELETE https://api.tryenvoyx.com/api/v1/invoices/{id} \
  -H "X-API-Key: YOUR_API_KEY"

Response:

{
  "success": true,
  "status": 200,
  "code": "INVOICE_DELETED",
  "message": "Invoice deleted successfully"
}

Deletion is permanent. The invoice file and all extracted data will be removed.

Update Invoice Status

Update the status of a processed invoice (e.g., approve, reject, or mark as paid).

curl -X PATCH https://api.tryenvoyx.com/api/v1/invoices/{id}/status \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "APPROVED"
  }'

Response:

{
  "success": true,
  "status": 200,
  "code": "STATUS_UPDATED",
  "message": "Invoice status updated successfully",
  "data": {
    "id": "clx1234567890",
    "status": "APPROVED",
    "updated_at": "2024-02-11T09:30:00Z"
  }
}

Status Lifecycle

Invoices follow this status progression:

PENDING → PROCESSING → PROCESSED → APPROVED → PAID
                     ↘ FLAGGED  → APPROVED → PAID
                     ↘ FAILED     REJECTED
StatusDescription
PENDINGUploaded, awaiting processing
PROCESSINGAI extraction in progress
PROCESSEDSuccessfully extracted and validated
FLAGGEDExtracted but validation issues detected
FAILEDExtraction or processing error
APPROVEDManually approved after review
REJECTEDManually rejected after review
PAIDMarked as paid

Valid Status Transitions

Not all transitions are allowed. The API enforces these rules:

FromAllowed To
PROCESSEDAPPROVED, REJECTED
FLAGGEDAPPROVED, REJECTED
APPROVEDPAID

System statuses (PENDING, PROCESSING, FAILED) are set automatically and cannot be changed via the API.

Processing Pipeline

Each invoice goes through a multi-step processing pipeline. You'll receive real-time progress via WebSocket or webhook events at each step.

StepDescription
1Starting processing
2Downloading from storage
3Summarizing invoice content
4Verifying category & amounts
5Identifying insurance company
6Checking partner approval
7Extracting structured fields
8Normalizing extracted data
9Checking for duplicates
10Validating submission date
11Computing risk assessment
12Finalizing results

Processing typically takes 15-25 seconds. Each step emits an invoice.processing event with the current step number, total steps, and a descriptive message.

Risk Scoring

After all verification checks run, a risk score and level are computed:

Risk LevelDescription
LOWAll checks passed — invoice processed normally
MEDIUMMinor issues detected — flagged for review
HIGHSignificant issues detected — flagged for review

If all checks pass, the invoice status is set to PROCESSED. If any check fails, it's set to FLAGGED.

Code Examples

Upload and Poll

const apiKey = process.env.ENVOYX_API_KEY

// Upload
const formData = new FormData()
formData.append('file', fs.createReadStream('invoice.pdf'))

const uploadRes = await fetch('https://api.tryenvoyx.com/api/v1/invoices/upload', {
  method: 'POST',
  headers: { 'X-API-Key': apiKey },
  body: formData,
})

const { data: invoice } = await uploadRes.json()
console.log('Uploaded:', invoice.id)

// Poll for completion
let status = 'PENDING'
while (status === 'PENDING' || status === 'PROCESSING') {
  await new Promise(r => setTimeout(r, 3000))

  const res = await fetch(`https://api.tryenvoyx.com/api/v1/invoices/${invoice.id}`, {
    headers: { 'X-API-Key': apiKey },
  })

  const { data } = await res.json()
  status = data.status
  console.log('Status:', status)
}
import requests
import time
import os

api_key = os.getenv('ENVOYX_API_KEY')
headers = {'X-API-Key': api_key}

# Upload
with open('invoice.pdf', 'rb') as f:
    res = requests.post(
        'https://api.tryenvoyx.com/api/v1/invoices/upload',
        headers=headers,
        files={'file': f}
    )

invoice = res.json()['data']
print(f"Uploaded: {invoice['id']}")

# Poll for completion
status = 'PENDING'
while status in ('PENDING', 'PROCESSING'):
    time.sleep(3)
    res = requests.get(
        f"https://api.tryenvoyx.com/api/v1/invoices/{invoice['id']}",
        headers=headers
    )
    status = res.json()['data']['status']
    print(f"Status: {status}")

Next Steps

On this page