Invoice Scanner API

Welcome to the Invoice Scanner API documentation. Our API allows you to programmatically scan, extract, and manage invoice data from PDF and image files.

Base URL: https://invoicescan.eu/api

Authentication

The Invoice Scanner API uses API keys to authenticate requests. You can generate API keys from your dashboard.

Using API Keys

Include your API key in the request header:

curl https://invoicescan.eu/api/invoices \
  -H "X-API-Key: sk_your_api_key_here"

Important: Keep your API keys secure. Do not share them in publicly accessible areas such as GitHub, client-side code, etc.

Rate Limits

API rate limits are based on your subscription plan:

Plan Scans/Month Price
Free 10 $0
Pro 1,000 $49
Ultimate 10,000 $99
Unlimited 100,000 $199

Error Handling

The API uses conventional HTTP response codes to indicate success or failure:

200 Success - Request completed successfully
400 Bad Request - Invalid parameters
401 Unauthorized - Invalid or missing API key
403 Forbidden - Subscription limit exceeded
404 Not Found - Resource not found
500 Server Error - Something went wrong on our end

Error Response Format

{
  "message": "Subscription limit exceeded",
  "errors": {
    "scans": ["You have used 10/10 scans this month"]
  }
}
POST

Upload Invoice

Upload an invoice file (PDF, JPG, PNG, DOC, DOCX) for processing. The API will extract structured data from the invoice.

Endpoint

POST /api/invoices

Request Parameters

Parameter Type Required Description
file file Yes Invoice file (PDF, JPG, PNG, DOC, DOCX, max 10MB)
company_id integer No Existing company ID to assign invoice to
company_name string No Company name to find or create
company_vat_id string No Company VAT ID to find or create (highest priority match)
company_tax_id string No Company Tax ID to find or create
auto_create_company boolean No Auto-create company if not found (default: false)
vendor_id integer No Vendor ID to assign to invoice
type string No Invoice type (e.g., 'purchase', 'sales')
is_hard_scan boolean No Mark as hard scan (requires manual review)
webhook_url string No URL to receive webhook notification when processing completes

Example Request

curl -X POST https://invoicescan.eu/api/invoices \
  -H "X-API-Key: sk_your_api_key_here" \
  -F "file=@/path/to/invoice.pdf" \
  -F "company_vat_id=BG123456789" \
  -F "auto_create_company=true" \
  -F "webhook_url=https://your-app.com/webhook"

Response (202 Accepted)

{
  "message": "Invoice uploaded successfully",
  "job_id": "019a7307-ec8a-72c4-9b3c-1b2ce9196b10",
  "status": "pending"
}
GET

Get Invoice

Retrieve the processing status and extracted data for a specific invoice.

Endpoint

GET /api/invoices/{id}

Example Request

curl https://invoicescan.eu/api/invoices/019a7307-ec8a-72c4-9b3c-1b2ce9196b10 \
  -H "X-API-Key: sk_your_api_key_here"

Response (200 OK)

{
  "job_id": "019a7307-ec8a-72c4-9b3c-1b2ce9196b10",
  "status": "completed",
  "result": {
    "invoice_number": "082000530981",
    "invoice_date": "15/10/2025",
    "vendor_name": "Hetzner Online GmbH",
    "vendor_address": "Industriestr. 25, 91710 Gunzenhausen, Germany",
    "customer_name": "MICROWEBER FINANCE EOOD",
    "customer_address": "Mr. Peter Ivanov, Bratq Chakrin 10, 1000 Sofia, Bulgaria",
    "line_items": [
      {
        "description": "AX41-NVMe Dedicated Server",
        "quantity": 288,
        "unit_price": "€0.0571",
        "total": "€16.4448"
      }
    ],
    "subtotal": "€310.42",
    "tax": "€0.00",
    "grand_total": "€310.42"
  },
  "error": null,
  "created_at": "2025-11-11T13:08:10Z",
  "updated_at": "2025-11-11T13:09:45Z"
}
GET

List Invoices

Retrieve a paginated list of all your invoices with optional filtering.

Endpoint

GET /api/invoices

Query Parameters

Parameter Type Description
page integer Page number (default: 1)
per_page integer Results per page (default: 20)
company_id integer Filter by company ID
company_name string Filter by company name (partial match)
company_vat_id string Filter by company VAT ID (normalized match)
company_tax_id string Filter by company Tax ID
vendor_id integer Filter by vendor ID
status string Filter by status: pending, processing, completed, failed
exclude_status string Exclude specific status
type string Filter by invoice type
is_checked boolean Filter by checked status (true/false)
date_from date Filter invoices from date (YYYY-MM-DD)
date_to date Filter invoices to date (YYYY-MM-DD)
sort string Sort field (created_at, updated_at)
order string Sort order (asc, desc)

Example Request

curl "https://invoicescan.eu/api/invoices?page=1&status=completed&company_vat_id=BG123456789" \
  -H "X-API-Key: sk_your_api_key_here"

Response (200 OK)

{
  "data": [
    {
      "job_id": "019a7307-ec8a-72c4-9b3c-1b2ce9196b10",
      "status": "completed",
      "session_id": null,
      "created_at": "2025-11-11T13:08:10Z",
      "updated_at": "2025-11-11T13:09:45Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "per_page": 20,
    "total": 1
  }
}
DELETE

Delete Invoice

Delete a specific invoice by its job ID.

Endpoint

DELETE /api/invoices/{id}

Example Request

curl -X DELETE https://invoicescan.eu/api/invoices/019a7307-ec8a-72c4-9b3c-1b2ce9196b10 \
  -H "X-API-Key: sk_your_api_key_here"

Response (200 OK)

{
  "message": "Invoice deleted successfully"
}
POST

Scan Invoice (Synchronous)

Upload and process an invoice synchronously. This endpoint waits for processing to complete and returns the extracted data immediately. Maximum wait time is configurable.

Endpoint

POST /api/invoices

Note: This is the same endpoint as async upload. The client polls the status endpoint automatically until completion or timeout.

Example Request

curl -X POST https://invoicescan.eu/api/invoices \
  -H "X-API-Key: sk_your_api_key_here" \
  -F "file=@/path/to/invoice.pdf"

# Then poll for results
curl https://invoicescan.eu/api/invoices/{job_id} \
  -H "X-API-Key: sk_your_api_key_here"
POST

Generate QR Code

Generate a QR code that redirects to the invoice scanner. Optionally link to a specific company.

Endpoint

POST /api/invoices/qr

Request Body

Parameter Type Required Description
company_id integer No Company ID to link QR code to (optional)

Example Request

curl -X POST https://invoicescan.eu/api/invoices/qr \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{"company_id": 1}'

Returns an SVG QR code image that can be displayed or saved.

Response

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="200" height="200">
  <!-- QR Code SVG content -->
</svg>
GET

List Companies

Retrieve a paginated list of all companies associated with your account.

Endpoint

GET /api/companies

Example Request

curl https://invoicescan.eu/api/companies \
  -H "X-API-Key: sk_your_api_key_here"

Response (200 OK)

{
  "data": [
    {
      "id": 1,
      "name": "ACME Corporation",
      "vat_number": "BG123456789",
      "address": "123 Business St",
      "created_at": "2025-01-01T00:00:00Z",
      "updated_at": "2025-01-01T00:00:00Z"
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 1,
    "per_page": 20,
    "total": 1
  }
}
POST

Create Company

Create a new company in your account.

Endpoint

POST /api/companies

Request Body

Parameter Type Required Description
name string Yes Company name
vat_number string No VAT/Tax identification number
address string No Company address

Example Request

curl -X POST https://invoicescan.eu/api/companies \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ACME Corporation",
    "vat_number": "BG123456789",
    "address": "123 Business St, Sofia, Bulgaria"
  }'

Response (201 Created)

{
  "id": 1,
  "name": "ACME Corporation",
  "vat_number": "BG123456789",
  "address": "123 Business St, Sofia, Bulgaria",
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T10:30:00Z"
}
PUT

Update Company

Update an existing company's information.

Endpoint

PUT /api/companies/{id}

Example Request

curl -X PUT https://invoicescan.eu/api/companies/1 \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ACME Corp Updated"
  }'
GET

Get Company

Retrieve details of a specific company by ID.

Endpoint

GET /api/companies/{id}

Example Request

curl https://invoicescan.eu/api/companies/1 \
  -H "X-API-Key: sk_your_api_key_here"

Response (200 OK)

{
  "id": 1,
  "name": "ACME Corporation",
  "vat_number": "BG123456789",
  "tax_id": "123456789",
  "address": "123 Business St, Sofia, Bulgaria",
  "email": null,
  "phone": null,
  "is_active": true,
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T10:30:00Z"
}
PUT

Update Company

Update an existing company's information.

Endpoint

PUT /api/companies/{id}

Example Request

curl -X PUT https://invoicescan.eu/api/companies/1 \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "ACME Corp Updated",
    "email": "contact@acmecorp.com"
  }'
DELETE

Delete Company

Delete a company from your account.

Endpoint

DELETE /api/companies/{id}

Example Request

curl -X DELETE https://invoicescan.eu/api/companies/1 \
  -H "X-API-Key: sk_your_api_key_here"
GET

Get Company Invoices

Get all invoices associated with a specific company.

Endpoint

GET /api/companies/{company_id}/invoices

Query Parameters

Parameter Type Description
status string Filter by status (pending, processing, completed, failed)
page integer Page number (default: 1)
per_page integer Results per page (default: 20)
sort_by string Sort field (default: created_at)
sort_order string Sort order: asc or desc (default: desc)

Example Request

curl "https://invoicescan.eu/api/companies/1/invoices?status=completed&page=1" \
  -H "X-API-Key: sk_your_api_key_here"

Response (200 OK)

{
  "data": [
    {
      "job_id": "019a7307-ec8a-72c4-9b3c-1b2ce9196b10",
      "status": "completed",
      "company_id": 1,
      "created_at": "2025-11-11T13:08:10Z",
      "updated_at": "2025-11-11T13:09:45Z",
      "result": {
        "invoice_number": "INV-2025-001",
        "grand_total": "€1,200.00",
        "..."
      }
    }
  ],
  "meta": {
    "current_page": 1,
    "last_page": 3,
    "per_page": 20,
    "total": 57
  }
}
POST

Extract Company Data

Extract company information from a document using AI (e.g., business card, letterhead).

Endpoint

POST /api/companies/extract

Request Parameters

Parameter Type Required Description
file file Yes Document file (PDF, JPG, PNG, max 10MB)

Example Request

curl -X POST https://invoicescan.eu/api/companies/extract \
  -H "X-API-Key: sk_your_api_key_here" \
  -F "file=@business_card.jpg"

Response (200 OK)

{
  "name": "Extracted Company Ltd",
  "vat_number": "BG123456789",
  "address": "123 Business Street, Sofia",
  "email": "contact@extracted.com",
  "phone": "+359 2 123 4567",
  "website": "https://extracted.com"
}
GET

List Vendors

Get all vendors for a specific company.

Endpoint

GET /api/companies/{company_id}/vendors

Example Request

curl https://invoicescan.eu/api/companies/1/vendors \
  -H "X-API-Key: sk_your_api_key_here"
POST

Create Vendor

Add a new vendor to a company.

Endpoint

POST /api/companies/{company_id}/vendors

Request Body

Parameter Type Required Description
vendor_name string Yes Vendor name
vendor_vat string No VAT number
vendor_address string No Vendor address

Example Request

curl -X POST https://invoicescan.eu/api/companies/1/vendors \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "vendor_name": "Office Supplies Inc",
    "vendor_vat": "VAT123456"
  }'

📊 Account Codes & Document Classification

🔍 Overview

Our system provides powerful invoice classification using two separate but complementary systems: user-defined account_code and AI-extracted document_code.

👤 Your Account Codes

What: Your company's custom accounting classification system

  • User-defined - You create and manage these codes
  • Company-specific - Different for each company
  • Examples: "60101" (Materials), "60201" (Goods), "6000" (Expenses)
  • Purpose: Internal categorization for your accounting system

🤖 AI Document Codes

What: Automatic classification based on Bulgarian Chart of Accounts

  • AI-extracted - Automatically determined from invoice content
  • Standardized - Based on Bulgarian accounting standards (Сметкоплан)
  • Examples: "601" (Materials), "602" (Goods), "704" (Services)
  • Cannot be changed - Reflects the invoice's actual nature

🎯 Key Concepts

account_code (User-Defined)

Your custom accounting codes for categorizing invoices in your system. You create and manage these via the API endpoints below. They can be linked to:

  • internal_code - Internal SKU/material codes for warehouse integration
  • barcode_mapping - Array of barcodes to automatically categorize products
  • description_mapping - Product descriptions for text-based matching
  • category - Additional categorization field

document_code (AI-Extracted)

Automatically extracted by our AI analyzing the invoice content against the Bulgarian Chart of Accounts. The AI considers:

  • Line item descriptions and nature
  • Transaction type (purchase, sale, expense)
  • Bulgarian accounting classification standards
  • Industry-specific patterns

Note: This field is automatically determined and cannot be manually set or changed. It reflects the true accounting nature of the transaction.

document_type_code (Bulgarian VAT)

Bulgarian VAT document classification (also AI-determined):

  • 01 - Фактура (Standard Invoice)
  • 02 - Дебитно известие (Debit Note)
  • 03 - Кредитно известие (Credit Note)
  • 11 - Фактура при касов метод (Cash-basis Invoice)
  • 12 - Дебитно известие при касов метод (Cash-basis Debit Note)
  • 13 - Кредитно известие при касов метод (Cash-basis Credit Note)

📦 Material & Goods Inventory Codes

Question: "При покупка на материали и стоки, които ще се заприхождават в склад има ли някаква функционалност, за настройка на кодове на материали и стоки?"

Answer: Yes! The CompanyAccountCode model supports extensive warehouse/inventory functionality through these fields:

internal_code

Internal SKU or material code for your warehouse system. Maps your account codes to specific products/materials in your inventory.

barcode_mapping

Array of barcodes. When an invoice line item has a matching barcode, it's automatically categorized to this account code.

description_mapping

Array of product descriptions for text-based matching. Automatically assigns account codes based on product names.

barcode_internal_code_mapping

Direct mapping from barcodes to internal codes, enabling complex warehouse/ERP integrations.

💡 Example: Create an account code "60101" (Materials) with internal_code: "MAT-001" and barcode_mapping: ["4820024700016", "4820024700023"]. When an invoice contains these barcodes, the system can automatically categorize and map to your warehouse inventory.

📋 JSON Response Fields Explanation

When you retrieve an invoice, the response includes these classification fields:

{
  "job_id": "019c763c-3196-706f-83eb-ca2f585f62f9",
  "status": "completed",
  "result": {
    // AI-Extracted Classification (Bulgarian Standards)
    "document_code": "601",
    "document_code_description": "Разходи за материали",
    "document_code_group": "60 - Operating Expenses",
    "document_code_confidence": 0.95,
    "document_code_reasoning": "Line items contain materials...",
    
    // Bulgarian VAT Classification
    "document_type_code": "01",
    "document_type_description": "Фактура",
    
    // Invoice Details
    "invoice_number": "INV-2025-001",
    "invoice_date": "2025-01-15",
    "vendor_name": "Supplier Ltd",
    "grand_total": "€1,200.00",
    
    // Line Items (may include your account codes if mapped)
    "line_items": [
      {
        "description": "Office Materials",
        "quantity": 10,
        "unit_price": "€100.00",
        "total": "€1,000.00",
        "account_code": "60101"  // Your custom code (if mapped)
      }
    ]
  }
}
document_code: The Bulgarian Chart of Accounts classification (e.g., "601" for Materials)
document_code_description: Human-readable description in Bulgarian
document_code_group: Higher-level grouping (e.g., "60 - Operating Expenses")
document_code_confidence: AI confidence score (0.0 to 1.0)
document_code_reasoning: Explanation of why this code was assigned
document_type_code: Bulgarian VAT document type (01-13)
line_items[].account_code: Your custom account code (if you've set up mapping rules)

🔄 Typical Workflow

  1. Create Company: Set up your company via POST /api/companies
  2. Define Account Codes: Create your accounting structure via POST /api/companies/{id}/account-codes
    • Add internal_code for warehouse SKUs
    • Add barcode_mapping for automatic product categorization
    • Add description_mapping for text-based matching
  3. Upload Invoices: Upload PDFs via POST /api/invoices
  4. AI Processing: System automatically extracts document_code (Bulgarian standard) and attempts to match your custom account_code via barcode/description mapping
  5. Retrieve Results: Get structured data with both AI classification and your custom codes
GET

List Account Codes

Get all account codes for a specific company.

Endpoint

GET /api/companies/{company_id}/account-codes

Example Request

curl https://invoicescan.eu/api/companies/1/account-codes \
  -H "X-API-Key: sk_your_api_key_here"
POST

Create Account Code

Add a new account code to a company.

Endpoint

POST /api/companies/{company_id}/account-codes

Request Body

Parameter Type Required Description
account_code string Yes Account code number
account_name string Yes Account name/description
account_type string Yes Type: expense, revenue, asset, liability

Example Request

curl -X POST https://invoicescan.eu/api/companies/1/account-codes \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "account_code": "6000",
    "account_name": "Office Supplies",
    "account_type": "expense"
  }'
POST

Bulk Import Account Codes

Import multiple account codes at once from tab-separated text.

Endpoint

POST /api/companies/{company_id}/account-codes/bulk-import

Request Body

Parameter Type Required Description
pasted_text string Yes Tab-separated account codes (code\tname per line)

Example Request

curl -X POST https://invoicescan.eu/api/companies/1/account-codes/bulk-import \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "pasted_text": "100\tCash\n200\tBank\n300\tAccounts Receivable"
  }'
POST

Bulk Delete Account Codes

Delete multiple account codes at once.

Endpoint

POST /api/companies/{company_id}/account-codes/bulk-delete

Request Body

Parameter Type Required Description
ids array Yes Array of account code IDs to delete

Example Request

curl -X POST https://invoicescan.eu/api/companies/1/account-codes/bulk-delete \
  -H "X-API-Key: sk_your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "ids": [1, 2, 3, 4, 5]
  }'

PHP SDK Example

Example using PHP to upload and process an invoice:

<?php

$apiKey = 'sk_your_api_key_here';
$apiUrl = 'https://invoicescan.eu/api/invoices';

// Upload invoice
$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL => $apiUrl,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'X-API-Key: ' . $apiKey,
    ],
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('/path/to/invoice.pdf'),
        'webhook_url' => 'https://your-app.com/webhook',
    ],
]);

$response = curl_exec($curl);
$result = json_decode($response, true);
curl_close($curl);

// Get job_id
$jobId = $result['job_id'];

// Poll for result
$maxAttempts = 30;
for ($i = 0; $i < $maxAttempts; $i++) {
    sleep(2);
    
    $curl = curl_init();
    curl_setopt_array($curl, [
        CURLOPT_URL => $apiUrl . '/' . $jobId,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'X-API-Key: ' . $apiKey,
        ],
    ]);
    
    $response = curl_exec($curl);
    $result = json_decode($response, true);
    curl_close($curl);
    
    if ($result['status'] === 'completed') {
        print_r($result['result']);
        break;
    }
}
POST

Analyze PDF File

Analyze a PDF file and extract each page as a base64 encoded image. This endpoint processes PDF files page-by-page and returns high-quality image representations of each page.

Endpoint

POST /api/invoices-file-analyze

Authentication

This endpoint requires authentication via Sanctum (session-based auth).

Request Parameters

Parameter Type Required Description
file file Yes PDF file to analyze (max 10MB)
scale number No Rendering scale (0.5 to 4.0, default: 2.0)
format string No Output format: jpeg or png (default: jpeg)
quality number No Image quality (0.1 to 1.0, default: 0.85)

Example Request (cURL)

curl -X POST https://invoicescan.eu/api/invoices-file-analyze \
  -H "Accept: application/json" \
  -H "Cookie: your-session-cookie" \
  -F "file=@/path/to/document.pdf" \
  -F "scale=2.0" \
  -F "format=jpeg" \
  -F "quality=0.85"

Example Request (JavaScript)

const formData = new FormData();
formData.append('file', pdfFile);
formData.append('scale', 2.0);
formData.append('format', 'jpeg');
formData.append('quality', 0.85);

const response = await fetch('/api/invoices-file-analyze', {
  method: 'POST',
  headers: {
    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
  },
  credentials: 'include',
  body: formData
});

const result = await response.json();
console.log(result);

Success Response (200 OK)

{
  "success": true,
  "numPages": 3,
  "pages": [
    {
      "pageNumber": 1,
      "width": 1654,
      "height": 2339,
      "image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
    },
    {
      "pageNumber": 2,
      "width": 1654,
      "height": 2339,
      "image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
    },
    {
      "pageNumber": 3,
      "width": 1654,
      "height": 2339,
      "image": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..."
    }
  ]
}

Error Response (500 Internal Server Error)

{
  "success": false,
  "error": "Failed to analyze PDF",
  "details": "Error message details..."
}

💡 Use Cases

  • Preview PDF pages before processing
  • Extract visual content for OCR processing
  • Generate thumbnails for PDF documents
  • Create image-based PDF viewers
  • Backend image processing and analysis

⚠️ Important Notes

  • Maximum file size: 10MB
  • Only PDF files are supported
  • Higher scale values produce larger images
  • JPEG format is recommended for smaller file sizes
  • Processing time increases with page count and scale