📖 API Reference
Complete documentation for ExtractBill REST API. Build invoice and receipt parsing into your application with our simple, powerful API.
Authentication
All API requests require authentication via Bearer token in the Authorization header. Your API tokens carry many privileges, so be sure to keep them secure! Do not share your secret API tokens in publicly accessible areas such as GitHub, client-side code, and so forth.
Get your API token
- Go to Dashboard → Settings → API Tokens
- Click "Generate New Token"
- Copy the token (shown only once!) and store it securely
Quick Admin Link
Already logged in? Create a token directly in admin panel:
Create API Token in SettingsToken Format
xb_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
API tokens are 43 characters long and start with xb_
Request Header
Include your API token in the Authorization header of every request:
Authorization: Bearer xb_your_token_here
Endpoints
/account/usage
Get detailed statistics about your account usage including total documents processed, success rate, average confidence scores, and processing times. This endpoint helps you monitor your API usage and performance metrics.
Request Example
curl https://www.extractbill.com/api/v1/account/usage \
-H "Authorization: Bearer xb_your_token"
const response = await fetch('https://www.extractbill.com/api/v1/account/usage', {
headers: {
'Authorization': 'Bearer xb_your_token'
}
});
const data = await response.json();
console.log(data);
import requests
response = requests.get(
'https://www.extractbill.com/api/v1/account/usage',
headers={'Authorization': 'Bearer xb_your_token'}
)
data = response.json()
print(data)
$client = new \GuzzleHttp\Client();
$response = $client->get('https://www.extractbill.com/api/v1/account/usage', [
'headers' => ['Authorization' => 'Bearer xb_your_token']
]);
$data = json_decode($response->getBody(), true);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://www.extractbill.com/api/v1/account/usage"))
.header("Authorization", "Bearer xb_your_token")
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer xb_your_token");
var response = await client.GetAsync("https://www.extractbill.com/api/v1/account/usage");
var data = await response.Content.ReadAsStringAsync();
Response (200 OK)
{
"data": {
"total_documents": 150,
"documents_this_month": 25,
"completed": 145,
"failed": 5,
"success_rate": 96.67,
"average_confidence_score": 94.2,
"average_processing_time_seconds": 4.8
}
}
Response Fields
total_documents
Total number of documents processed across all time
documents_this_month
Documents processed in the current calendar month
success_rate
Percentage of successfully processed documents (0-100)
average_confidence_score
Average AI confidence score for completed documents (0-100)
average_processing_time_seconds
Average time to process a document from upload to completion
/account/balance
Retrieve your current token balance and purchase history. Use this endpoint to check if you have sufficient tokens before uploading documents, or to display balance information in your application.
Response (200 OK)
{
"data": {
"current_balance": 47,
"total_purchased": 100,
"total_used": 53,
"usage_percentage": 53.00,
"last_purchase_at": "2025-09-01T10:00:00Z"
}
}
Response Fields
current_balance
Number of tokens available for document processing
total_purchased
Total tokens purchased (including free trial tokens)
usage_percentage
Percentage of purchased tokens that have been used
/documents
Upload a document (invoice, receipt, or bill) for AI-powered parsing. The document will be processed asynchronously - you'll receive an immediate response with a document ID that you can use to check the status and retrieve parsed data once processing is complete.
Need higher limits? Contact us
Parameters
file
webhook_url
webhook_secret
Request Example
curl -X POST https://www.extractbill.com/api/v1/documents \
-H "Authorization: Bearer xb_your_token" \
-F "file=@invoice.pdf"
const formData = new FormData();
formData.append('file', fileInput.files[0]);
const response = await fetch('https://www.extractbill.com/api/v1/documents', {
method: 'POST',
headers: { 'Authorization': 'Bearer xb_your_token' },
body: formData
});
const data = await response.json();
import requests
with open('invoice.pdf', 'rb') as f:
files = {'file': f}
response = requests.post(
'https://www.extractbill.com/api/v1/documents',
headers={'Authorization': 'Bearer xb_your_token'},
files=files
)
data = response.json()
$client = new \GuzzleHttp\Client();
$response = $client->post('https://www.extractbill.com/api/v1/documents', [
'headers' => ['Authorization' => 'Bearer xb_your_token'],
'multipart' => [
['name' => 'file', 'contents' => fopen('invoice.pdf', 'r')]
]
]);
$data = json_decode($response->getBody(), true);
var file = new File("invoice.pdf");
var request = HttpRequest.newBuilder()
.uri(URI.create("https://www.extractbill.com/api/v1/documents"))
.header("Authorization", "Bearer xb_your_token")
.header("Content-Type", "multipart/form-data")
.POST(HttpRequest.BodyPublishers.ofFile(file.toPath()))
.build();
var response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var fileContent = new StreamContent(File.OpenRead("invoice.pdf"));
content.Add(fileContent, "file", "invoice.pdf");
client.DefaultRequestHeaders.Add("Authorization", "Bearer xb_your_token");
var response = await client.PostAsync("https://www.extractbill.com/api/v1/documents", content);
Response (202 Accepted)
{
"data": {
"id": "d-a3k9f2x7m1p",
"status": "pending",
"original_filename": "invoice.pdf",
"uploaded_at": "2025-10-14T14:30:00Z",
"uploaded_via": "api"
}
}
Possible Errors
400
Invalid file format - only PDF, JPG, PNG, WEBP are supported
402
Insufficient tokens - purchase more tokens to continue
413
File too large (max 10MB)
422
Validation error - check request parameters
429
Rate limit exceeded - wait before making more requests
/documents/:id
Retrieve the current status and parsed data for a specific document. Use this endpoint to poll for completion after uploading a document. Once processing is complete, you'll receive the full parsed data in structured JSON format.
Request Example
curl https://www.extractbill.com/api/v1/documents/d-a3k9f2x7m1p \
-H "Authorization: Bearer xb_your_token"
const documentId = 'd-a3k9f2x7m1p';
const response = await fetch(`https://www.extractbill.com/api/v1/documents/${documentId}`, {
headers: { 'Authorization': 'Bearer xb_your_token' }
});
const data = await response.json();
import requests
document_id = 'd-a3k9f2x7m1p'
response = requests.get(
f'https://www.extractbill.com/api/v1/documents/{document_id}',
headers={'Authorization': 'Bearer xb_your_token'}
)
data = response.json()
$client = new \GuzzleHttp\Client();
$documentId = 'd-a3k9f2x7m1p';
$response = $client->get("https://www.extractbill.com/api/v1/documents/{$documentId}", [
'headers' => ['Authorization' => 'Bearer xb_your_token']
]);
$data = json_decode($response->getBody(), true);
String documentId = "d-a3k9f2x7m1p";
var request = HttpRequest.newBuilder()
.uri(URI.create("https://www.extractbill.com/api/v1/documents/" + documentId))
.header("Authorization", "Bearer xb_your_token")
.GET()
.build();
var response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
using var client = new HttpClient();
string documentId = "d-a3k9f2x7m1p";
client.DefaultRequestHeaders.Add("Authorization", "Bearer xb_your_token");
var response = await client.GetAsync($"https://www.extractbill.com/api/v1/documents/{documentId}");
var data = await response.Content.ReadAsStringAsync();
Response (200 OK)
{
"data": {
"id": "d-a3k9f2x7m1p",
"status": "completed",
"confidence_score": 95.5,
"parsed_data": {
"document": {
"type": "invoice",
"identifier": "INV-2025-001",
"date": "2025-10-10",
"due_date": "2025-11-10"
},
"supplier": {
"name": "ACME Corporation",
"address": "123 Main St, New York, NY 10001",
"tax_id": "12-3456789"
},
"customer": {
"name": "John Doe",
"address": "456 Oak Ave, Los Angeles, CA 90001"
},
"totals": {
"subtotal": 1000.00,
"tax": 250.00,
"total": 1250.00,
"currency": "USD"
},
"items": [
{
"description": "Professional Services",
"quantity": 10,
"unit_price": 100.00,
"amount": 1000.00
}
]
},
"completed_at": "2025-10-14T14:30:05Z",
"processing_time_seconds": 5
}
}
Status Values
pending
Document uploaded, waiting to be processed
processing
AI is currently parsing the document
completed
Parsing complete, data available in parsed_data field
failed
Processing failed, check error_message field
/documents
List all documents for your account with pagination and filtering options. Use this to build document management interfaces or to monitor processing status across multiple uploads.
Query Parameters
page
per_page
status
Request Example
curl "https://www.extractbill.com/api/v1/documents?status=completed&per_page=20" \
-H "Authorization: Bearer xb_your_token"
const params = new URLSearchParams({
status: 'completed',
per_page: '20'
});
const response = await fetch(`https://www.extractbill.com/api/v1/documents?${params}`, {
headers: { 'Authorization': 'Bearer xb_your_token' }
});
const data = await response.json();
import requests
params = {'status': 'completed', 'per_page': 20}
response = requests.get(
'https://www.extractbill.com/api/v1/documents',
headers={'Authorization': 'Bearer xb_your_token'},
params=params
)
data = response.json()
$client = new \GuzzleHttp\Client();
$response = $client->get('https://www.extractbill.com/api/v1/documents', [
'headers' => ['Authorization' => 'Bearer xb_your_token'],
'query' => ['status' => 'completed', 'per_page' => 20]
]);
$data = json_decode($response->getBody(), true);
var request = HttpRequest.newBuilder()
.uri(URI.create("https://www.extractbill.com/api/v1/documents?status=completed&per_page=20"))
.header("Authorization", "Bearer xb_your_token")
.GET()
.build();
var response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer xb_your_token");
var query = "?status=completed&per_page=20";
var response = await client.GetAsync($"https://www.extractbill.com/api/v1/documents{query}");
var data = await response.Content.ReadAsStringAsync();
Error Handling
All errors return a consistent JSON format with a descriptive error code, human-readable message, and additional details when available. This structure makes it easy to handle errors programmatically in your application.
Error Response Format
{
"error": {
"code": "insufficient_tokens",
"message": "Insufficient token balance",
"details": {
"current_balance": 0,
"required": 1,
"purchase_url": "https://www.extractbill.com/settings/billing"
}
}
}
Common Error Codes
401
402
403
404
422
429
500
More Examples
Real-world examples to help you integrate ExtractBill API into your application.
Upload Document with Custom Webhook Notification
Upload a document and receive a webhook notification when processing completes:
💡 Tip: You can set a global webhook URL for all documents in Admin Settings. Per-request webhook URLs override the global setting. Learn more in Webhooks Documentation.
curl -X POST https://www.extractbill.com/api/v1/documents \
-H "Authorization: Bearer xb_your_token" \
-F "file=@invoice.pdf" \
-F "webhook_url=https://your-app.com/webhooks/extractbill" \
-F "webhook_secret=your_webhook_secret_123"
Check Balance Before Upload
Always check your balance before uploading to avoid 402 errors:
# 1. Check balance
curl https://www.extractbill.com/api/v1/account/balance \
-H "Authorization: Bearer xb_your_token"
# 2. If balance > 0, upload document
curl -X POST https://www.extractbill.com/api/v1/documents \
-H "Authorization: Bearer xb_your_token" \
-F "file=@invoice.pdf"
Poll for Document Completion
Simple polling loop to wait for document processing:
# Upload document
DOCUMENT_ID=$(curl -X POST https://www.extractbill.com/api/v1/documents \
-H "Authorization: Bearer xb_your_token" \
-F "file=@invoice.pdf" | jq -r '.data.id')
# Poll every 2 seconds until completed
while true; do
STATUS=$(curl https://www.extractbill.com/api/v1/documents/$DOCUMENT_ID \
-H "Authorization: Bearer xb_your_token" | jq -r '.data.status')
if [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ]; then
break
fi
sleep 2
done
# Get final result
curl https://www.extractbill.com/api/v1/documents/$DOCUMENT_ID \
-H "Authorization: Bearer xb_your_token"
List Only Failed Documents
Get all failed documents to investigate processing issues:
curl "https://www.extractbill.com/api/v1/documents?status=failed&per_page=50" \
-H "Authorization: Bearer xb_your_token"
Need help integrating?
Check out our Getting Started guide for step-by-step instructions, or contact our support team if you need assistance.