Invoice Data Extraction API Documentation

Integrate invoice data extraction directly into your product with a simple, secure API.

Authentication

Authenticate every request with an API token created in your dashboard.

Create a personal API token, then include it in the Authorization header on each call:

Authorization: Bearer YOUR_API_TOKEN

To create an API token:

  1. Log in to your InvoiceExtractor account
  2. Navigate to the API section
  3. Click "Create API Token" and follow the instructions

Token roles and permissions

Each token carries its own permissions, so a reporting script can read results without being able to upload, and an intake service can upload without reading anything else. A call outside the token's permissions returns HTTP 403. Uploads and result reads made with a token are recorded in your activity log under the token's name and role.

When you create a token you pick its role. Each role is a fixed set of permissions, and you can still adjust the permissions by hand, in which case the token shows as Custom.

RolePermissionsTypical use
Full accessupload-documents, extract-data, view-extractions, read Uploads invoices, starts extractions and reads every result. For an integration that runs the whole flow.
Intakeupload-documents, extract-data, read Uploads invoices and starts extractions. Cannot read extracted data. For a scanner, mailbox or upload service.
Read onlyview-extractions, read Reads extraction results. Cannot upload or start extractions. For reporting, BI and accounting sync.
PermissionAllows
upload-documentsPOST /api/documents/upload
extract-dataPOST /api/documents/extract (only files uploaded by your account)
view-extractionsGET /api/documents/extraction/{hash}
readGET /api/documents/types

API Endpoints

Core endpoints for upload, extraction, and results

Upload Document

POST /api/documents/upload

Upload an invoice file to begin processing.

Request

Content-Type: multipart/form-data


{
  "document": [file] // Required: The document file to upload
}

Response


{
  "success": true,
  "message": "File uploaded successfully",
  "data": {
    "file_id": 1234,
    "name": "invoice.pdf"
  }
}

Extract Data

POST /api/documents/extract

Start extraction for a previously uploaded file.

Request

Content-Type: application/json


{
  "file_id": 1234,                // Required: ID of the uploaded file
  "document_type_id": 5678        // Optional: ID of the document template to use
}

Response


{
  "success": true,
  "message": "Extraction initialized successfully",
  "data": {
    "extraction_id": 9876,
    "extraction_hash": "abc123-def456-ghi789-jkl012"
  }
}

Get Extraction Results

GET /api/documents/extraction/{hash}

Fetch the parsed results for a given extraction hash.

Parameters

{hash}: The extraction hash returned by the extract endpoint

Response


{
  "success": true,
  "data": {
    "extraction_id": 9876,
    "extraction_hash": "abc123-def456-ghi789-jkl012",
    "file": {
      "id": 1234,
      "name": "invoice.pdf"
    },
    "document_type": {
      "id": 5678,
      "name": "Invoice Template"
    },
    "fields": [
      {
        "field_id": 101,
        "content": "Account Number",
        "value": "1234567890",
        "is_table": false,
        "page": 1
      },
      {
        "field_id": 102,
        "content": "Statement Date",
        "value": "2023-05-15",
        "is_table": false,
        "page": 1
      },
      {
        "field_id": 103,
        "content": "Balance",
        "value": "$12,450.00",
        "is_table": false,
        "page": 1
      },
      {
        "field_id": 104,
        "content": "Transactions",
        "is_table": true,
        "page": 1,
        "rows": [
          {
            "cells": [
              {"value": "2023-05-10", "is_header": false},
              {"value": "DEPOSIT", "is_header": false},
              {"value": "$500.00", "is_header": false}
            ]
          },
          {
            "cells": [
              {"value": "2023-05-12", "is_header": false},
              {"value": "WITHDRAWAL", "is_header": false},
              {"value": "-$250.00", "is_header": false}
            ]
          }
        ]
      }
    ]
  }
}

Get Document Types

GET /api/documents/types

Retrieve a list of available document templates.

Response


{
  "success": true,
  "data": [
    {
      "id": 5678,
      "name": "Invoice Template",
      "description": "Template for processing invoice documents",
      "is_public": true,
      "fields_count": 10
    },
    {
      "id": 5679,
      "name": "Purchase Order Template",
      "description": "Template for processing purchase order documents",
      "is_public": false,
      "fields_count": 8
    }
  ]
}

Webhooks

Get notified the moment an extraction finishes instead of polling.

Add an HTTPS endpoint in your dashboard under Webhooks and choose the events it receives. We send a POST with a JSON body when an extraction you started (in the dashboard or through the API) reaches its final state.

EventSent when
extraction.completedAll pages are processed. data.status is completed, or partial if some pages could not be read.
extraction.failedNo page could be extracted, or the plan limit stopped the job.
pingYou press Send test event.

Payload

{
  "id": "evt_8k2m4q9x1c7v5b3n6z0p2r4t",
  "type": "extraction.completed",
  "created": 1767225600,
  "data": {
    "extraction_id": 1234,
    "extraction_hash": "abc123-def456-ghi789-jkl012",
    "status": "completed",
    "file": { "id": 5678, "name": "invoice-1042.pdf" },
    "document_type": null,
    "fields": [
      { "field_id": 1, "content": "Invoice Number", "value": "INV-1042", "is_table": false, "page": 1 }
    ],
    "pages": [ { "page": 1, "status": "completed" } ],
    "results_url": "https://invoiceextractor.ai/api/documents/extraction/abc123-def456-ghi789-jkl012"
  }
}

Verifying the signature

Every request carries InvoiceExtractor-Signature: t=<unix time>,v1=<hex>, where v1 is HMAC SHA-256 of t + "." + raw request body with your endpoint's signing secret. Reject requests whose signature does not match or whose t is older than five minutes. The headers InvoiceExtractor-Event and InvoiceExtractor-Delivery carry the event type and a unique delivery ID you can use to ignore duplicates.

// PHP
$body = file_get_contents('php://input');
parse_str(str_replace(',', '&', $_SERVER['HTTP_INVOICEEXTRACTOR_SIGNATURE'] ?? ''), $sig);
$expected = hash_hmac('sha256', $sig['t'] . '.' . $body, getenv('INVOICEEXTRACTOR_WEBHOOK_SECRET'));
if (!hash_equals($expected, $sig['v1'] ?? '') || abs(time() - (int) $sig['t']) > 300) {
    http_response_code(400);
    exit;
}

# Python
import hmac, hashlib, time
parts = dict(p.split("=", 1) for p in request.headers["InvoiceExtractor-Signature"].split(","))
expected = hmac.new(secret.encode(), (parts["t"] + "." + request.get_data(as_text=True)).encode(), hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, parts["v1"]) and abs(time.time() - int(parts["t"])) <= 300

Retries

Answer with any 2xx status within 10 seconds. Other responses and timeouts are retried after 1 minute, 5 minutes, 15 minutes, 1 hour and 3 hours. Redirects are not followed. An endpoint that fails 15 deliveries in a row is disabled and can be enabled again in the dashboard, where you also see recent deliveries and can retry a failed one.

Webhooks are part of API access on the Pro plans.

Code Examples

Copy‑paste snippets to integrate invoice data extraction in minutes

Upload and extract with cURL


# Upload document
curl -X POST https://invoiceextractor.ai/api/documents/upload \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "document=@/path/to/document.pdf"

# Extract data
curl -X POST https://invoiceextractor.ai/api/documents/extract \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"file_id": 1234, "document_type_id": 5678}'

# Get results
curl -X GET https://invoiceextractor.ai/api/documents/extraction/abc123-def456-ghi789-jkl012 \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Complete invoice data extraction in PHP


<?php

$apiToken = 'YOUR_API_TOKEN';
$apiBaseUrl = 'https://invoiceextractor.ai/api';

// 1. Upload document
$filePath = '/path/to/document.pdf';
$ch = curl_init("$apiBaseUrl/documents/upload");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer $apiToken"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    'document' => new CURLFile($filePath)
]);

$uploadResponse = curl_exec($ch);
curl_close($ch);

$uploadResult = json_decode($uploadResponse, true);
if (!$uploadResult['success']) {
    die('Error uploading document: ' . $uploadResult['message']);
}

$fileId = $uploadResult['data']['file_id'];
echo "File uploaded with ID: $fileId\n";

// 2. Extract data
$ch = curl_init("$apiBaseUrl/documents/extract");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer $apiToken",
    "Content-Type: application/json"
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
    'file_id' => $fileId,
    'document_type_id' => 5678 // Optional
]));

$extractResponse = curl_exec($ch);
curl_close($ch);

$extractResult = json_decode($extractResponse, true);
if (!$extractResult['success']) {
    die('Error extracting data: ' . $extractResult['message']);
}

$extractionHash = $extractResult['data']['extraction_hash'];
echo "Extraction initialized with hash: $extractionHash\n";

// 3. Get extraction results
$ch = curl_init("$apiBaseUrl/documents/extraction/$extractionHash");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    "Authorization: Bearer $apiToken"
]);

$resultsResponse = curl_exec($ch);
curl_close($ch);

$resultsData = json_decode($resultsResponse, true);
if (!$resultsData['success']) {
    die('Error getting extraction results: ' . $resultsData['message']);
}

// Process the extracted data
$fields = $resultsData['data']['fields'];
foreach ($fields as $field) {
    echo $field['content'] . ': ' . $field['value'] . "\n";
}

Complete invoice data extraction in JavaScript


// Complete document processing with JavaScript
const apiToken = 'YOUR_API_TOKEN';
const apiBaseUrl = 'https://invoiceextractor.ai/api';

// 1. Upload document
async function uploadDocument(filePath) {
  const formData = new FormData();
  formData.append('document', document.querySelector('input[type="file"]').files[0]);

  const response = await fetch(`${apiBaseUrl}/documents/upload`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiToken}`
    },
    body: formData
  });

  const result = await response.json();
  if (!result.success) {
    throw new Error(`Error uploading document: ${result.message}`);
  }

  console.log(`File uploaded with ID: ${result.data.file_id}`);
  return result.data.file_id;
}

// 2. Extract data
async function extractData(fileId, documentTypeId = null) {
  const payload = {
    file_id: fileId
  };

  if (documentTypeId) {
    payload.document_type_id = documentTypeId;
  }

  const response = await fetch(`${apiBaseUrl}/documents/extract`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${apiToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(payload)
  });

  const result = await response.json();
  if (!result.success) {
    throw new Error(`Error extracting data: ${result.message}`);
  }

  console.log(`Extraction initialized with hash: ${result.data.extraction_hash}`);
  return result.data.extraction_hash;
}

// 3. Get extraction results
async function getExtractionResults(extractionHash) {
  const response = await fetch(`${apiBaseUrl}/documents/extraction/${extractionHash}`, {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${apiToken}`
    }
  });

  const result = await response.json();
  if (!result.success) {
    throw new Error(`Error getting extraction results: ${result.message}`);
  }

  console.log('Extraction results:', result.data);

  // Process the extracted data
  const fields = result.data.fields;
  fields.forEach(field => {
    console.log(`${field.content}: ${field.value}`);
  });

  return result.data;
}

// Usage
async function processDocument() {
  try {
    const fileId = await uploadDocument();
    const extractionHash = await extractData(fileId, 5678); // Optional document type ID
    const extractionData = await getExtractionResults(extractionHash);

    // Do something with the extracted data
    displayResults(extractionData);
  } catch (error) {
    console.error(error);
  }
}

function displayResults(data) {
  // Display the results in your application
  const resultsDiv = document.getElementById('results');
  resultsDiv.innerHTML = '';

  data.fields.forEach(field => {
    const fieldEl = document.createElement('div');
    fieldEl.classList.add('field');
    fieldEl.innerHTML = `${field.content}: ${field.value}`;
    resultsDiv.appendChild(fieldEl);
  });
}

Complete invoice data extraction in Python


import requests
import json
import time

api_token = 'YOUR_API_TOKEN'
api_base_url = 'https://invoiceextractor.ai/api'

# 1. Upload document
def upload_document(file_path):
    headers = {
        'Authorization': f'Bearer {api_token}'
    }

    with open(file_path, 'rb') as file:
        files = {'document': file}
        response = requests.post(
            f'{api_base_url}/documents/upload',
            headers=headers,
            files=files
        )

    result = response.json()
    if not result.get('success'):
        raise Exception(f"Error uploading document: {result.get('message')}")

    file_id = result['data']['file_id']
    print(f"File uploaded with ID: {file_id}")
    return file_id

# 2. Extract data
def extract_data(file_id, document_type_id=None):
    headers = {
        'Authorization': f'Bearer {api_token}',
        'Content-Type': 'application/json'
    }

    payload = {
        'file_id': file_id
    }

    if document_type_id:
        payload['document_type_id'] = document_type_id

    response = requests.post(
        f'{api_base_url}/documents/extract',
        headers=headers,
        data=json.dumps(payload)
    )

    result = response.json()
    if not result.get('success'):
        raise Exception(f"Error extracting data: {result.get('message')}")

    extraction_hash = result['data']['extraction_hash']
    print(f"Extraction initialized with hash: {extraction_hash}")
    return extraction_hash

# 3. Get extraction results
def get_extraction_results(extraction_hash):
    headers = {
        'Authorization': f'Bearer {api_token}'
    }

    response = requests.get(
        f'{api_base_url}/documents/extraction/{extraction_hash}',
        headers=headers
    )

    result = response.json()
    if not result.get('success'):
        raise Exception(f"Error getting extraction results: {result.get('message')}")

    print("Extraction results:")
    fields = result['data']['fields']
    for field in fields:
        print(f"{field['content']}: {field['value']}")

    return result['data']

# Usage
def process_document(file_path, document_type_id=None):
    try:
        # Upload document
        file_id = upload_document(file_path)

        # Extract data
        extraction_hash = extract_data(file_id, document_type_id)

        # Get results (you might need to wait for processing to complete)
        time.sleep(2)  # Simple delay to wait for processing
        extraction_data = get_extraction_results(extraction_hash)

        # Process the extracted data further if needed
        return extraction_data
    except Exception as e:
        print(f"Error: {str(e)}")
        return None

# Process invoice
if __name__ == "__main__":
    result = process_document('/path/to/invoice.pdf', 5678)  # Optional document type ID
    print(json.dumps(result, indent=2))

Rate Limits & Support

Operational limits and how to get help

Rate Limits

Rate limits for Pro plan:

  • Pro plan: 500 requests per hour

Exceeding these limits returns HTTP 429 (Too Many Requests). Response headers indicate when you can retry.

Support

If you have any questions or need assistance with our API, please contact us: