Receipt Processing API
Transform receipt images into structured JSON data in seconds. Our OCR-powered API extracts transaction details, account information, amounts, and timestamps from bank transfer receipts.
Getting Started: Create an account and generate your API token from your profile settings to start processing receipts.
Authentication
All API requests require a Bearer token in the Authorization header.
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://readceipt.com/api/receipts
Get your API token: Navigate to your Profile page after signing up to generate tokens.
Base URL
https://readceipt.com/api
Process Receipt
Upload a receipt image and extract structured transaction data.
Request
POST /receipts
Content-Type: multipart/form-data
Authorization: Bearer YOUR_API_TOKEN
Parameters:
receipt(file, required) - Image file up to 10MB- Supported formats: JPEG, PNG, PDF, WebP
Examples
curl -X POST "https://readceipt.com/api/receipts" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-F "[email protected]"
const formData = new FormData();
formData.append('receipt', fileInput.files[0]);
const response = await fetch('https://readceipt.com/api/receipts', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_TOKEN'
},
body: formData
});
const result = await response.json();
import requests
headers = {'Authorization': 'Bearer YOUR_API_TOKEN'}
files = {'receipt': open('receipt.jpg', 'rb')}
response = requests.post(
'https://readceipt.com/api/receipts',
headers=headers,
files=files
)
result = response.json()
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://readceipt.com/api/receipts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer YOUR_API_TOKEN"
],
CURLOPT_POSTFIELDS => [
'receipt' => new CURLFile('receipt.jpg')
]
]);
$response = curl_exec($curl);
$result = json_decode($response, true);
?>
<?php
use Illuminate\Support\Facades\Http;
$response = Http::withToken('YOUR_API_TOKEN')
->attach('receipt', file_get_contents('receipt.jpg'), 'receipt.jpg')
->post('https://readceipt.com/api/receipts');
$result = $response->json();
// Or using a service class
class ReceiptService
{
public function processReceipt($filePath)
{
return Http::withToken(config('services.readceipt.token'))
->attach('receipt', file_get_contents($filePath), basename($filePath))
->post('https://readceipt.com/api/receipts')
->json();
}
}
?>
require 'net/http'
require 'uri'
uri = URI('https://readceipt.com/api/receipts')
request = Net::HTTP::Post.new(uri)
request['Authorization'] = 'Bearer YOUR_API_TOKEN'
form_data = [['receipt', File.open('receipt.jpg')]]
request.set_form(form_data, 'multipart/form-data')
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
result = JSON.parse(response.body)
Response
Success (200 OK):
{
"status": "SUCCESS",
"reference": "FT23120512345678",
"transaction_datetime": "2023-12-05T14:30:25",
"destination_bank_name": "Bank of Maldives",
"amount": {
"currency": "MVR",
"amount": 1500.00
},
"from_account": {
"account_name": "John Doe",
"account_number": "7701234567890"
},
"to_account": {
"account_name": "Jane Smith",
"account_number": "7709876543210"
},
"remarks": "Payment for services",
"type": "bml",
"verified": true,
"parsed_at": "2023-12-05T14:30:47Z",
"duration_ms": 847
}
With Warnings:
{
"status": "SUCCESS",
"reference": "FT23120512345678",
"transaction_datetime": "2023-12-05T14:30:25",
"destination_bank_name": "Bank of Maldives",
"amount": {
"currency": "MVR",
"amount": 1500.00
},
"from_account": {
"account_name": "John Doe",
"account_number": "7701234567890"
},
"to_account": {
"account_name": "Jane Smith",
"account_number": "7709876543210"
},
"remarks": "Payment for services",
"type": "bml",
"verified": false,
"parsed_at": "2023-12-05T14:30:47Z",
"duration_ms": 847,
"warnings": [
"Amount MVR 1500.0 not clearly found in OCR text"
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
status | string | Transaction status |
reference | string | Unique transaction reference |
transaction_datetime | string | Date and time in ISO 8601 format (YYYY-MM-DDTHH:MM:SS) |
destination_bank_name | string? | Name of destination bank |
amount.currency | string | Currency code (MVR, USD, etc.) |
amount.amount | number | Transaction amount |
from_account.account_name | string | Sender name |
from_account.account_number | string? | Sender account number |
to_account.account_name | string | Recipient name |
to_account.account_number | string? | Recipient account number |
remarks | string? | Transaction remarks or notes |
type | string | Bank type (bml, mib, or other) |
verified | boolean | Whether data passed all verification checks |
parsed_at | string | ISO 8601 timestamp when parsing completed (UTC) |
duration_ms | number | Processing time in milliseconds |
warnings | string? | Data quality warnings (null if verified is true) |
New Fields: The response now includes verified, parsed_at, and warnings fields to help you assess data quality. Fields marked with ? are optional.
Data Quality: When verified is false, check the warnings array for specific issues. The extracted data is still likely correct, but you should review it before use.
Error Handling
All errors return JSON with descriptive messages:
{
"message": "Error description here"
}
Status Codes
| Code | Error | Description |
|---|---|---|
400 | Bad Request | Invalid file format or corrupted image |
401 | Unauthorized | Missing or invalid API token |
403 | Forbidden | Rate limit or quota exceeded |
413 | Payload Too Large | File exceeds 10MB limit |
422 | Unprocessable Entity | Cannot extract data from image |
500 | Internal Server Error | Processing error occurred |
Common Errors
{
"message": "Invalid bearer token"
}
{
"message": "You have exceeded your allowed number of requests for your subscription plan. Please upgrade your plan to continue using the service."
}
{
"message": "Unsupported receipt format"
}
Rate Limits
Usage limits are based on your subscription plan:
| Plan | Monthly Requests | Per Minute | File Size |
|---|---|---|---|
| Free | 10 | 2 | 5MB |
| Starter | 100 | 10 | 10MB |
| Pro | 1,000 | 60 | 10MB |
| Enterprise | 10,000+ | 120 | 25MB |
Rate Limit Headers: Each response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers.
Best Practices
Image Quality
- Use clear, well-lit images
- Ensure text is readable and not blurred
- Avoid shadows or reflections
- Crop to focus on the receipt content
Data Quality & Warnings
The API now provides data quality indicators with each response:
const result = await response.json();
if (!result.verified) {
console.warn('Data quality issues detected:', result.warnings);
// Example warnings:
// - "Reference partially matched in OCR (possible OCR error)"
// - "Amount MVR 1500.0 not clearly found in OCR text"
// - "Currency 'MVR' not found in OCR text"
// Decide how to handle based on your use case:
// - Show warnings to user for review
// - Request manual verification
// - Flag for quality assurance
}
// The data is still extracted, even with warnings
processReceipt(result);
Understanding Verification Status:
verified: true- All data fully validated against OCR text (high confidence)verified: false- Some data couldn't be fully verified (check warnings array)
Common Warnings:
| Warning | Meaning | Action |
|---|---|---|
| "Reference partially matched" | OCR may have misread part of reference | Usually safe, OCR error |
| "Amount not clearly found" | Amount value not detected in OCR | Verify amount is correct |
| "Currency not found" | Currency code missing from OCR | Check currency matches receipt |
| "Account name not found" | Account name not in OCR text | Verify account details |
Error Handling
try {
const response = await fetch('/receipts', options);
if (!response.ok) {
const error = await response.json();
throw new Error(error.message);
}
const data = await response.json();
// Handle warnings if present
if (!data.verified && data.warnings) {
console.warn('Receipt processed with warnings:', data.warnings);
// Optionally prompt user to review
}
return data;
} catch (error) {
console.error('Receipt processing failed:', error.message);
// Handle error appropriately
}
Security
- Store API tokens securely
- Never expose tokens in client-side code
- Use environment variables for tokens
- Rotate tokens regularly
Working with DateTime
The API returns combined date and time in ISO 8601 format:
const result = await response.json();
// Parse the datetime
const transactionDate = new Date(result.transaction_datetime);
console.log(transactionDate.toLocaleDateString()); // "12/5/2023"
console.log(transactionDate.toLocaleTimeString()); // "2:30:25 PM"
console.log(transactionDate.toLocaleString()); // "12/5/2023, 2:30:25 PM"
// Format with date-fns or moment.js
import { format } from 'date-fns';
const formatted = format(transactionDate, 'PPpp'); // "Dec 5, 2023 at 2:30:25 PM"
from datetime import datetime
result = response.json()
# Parse the datetime (naive, no timezone)
transaction_dt = datetime.fromisoformat(result['transaction_datetime'])
print(transaction_dt.strftime('%Y-%m-%d')) # "2023-12-05"
print(transaction_dt.strftime('%H:%M:%S')) # "14:30:25"
print(transaction_dt.strftime('%B %d, %Y at %I:%M %p')) # "December 05, 2023 at 02:30 PM"
<?php
$result = json_decode($response, true);
// Parse the datetime
$transactionDate = new DateTime($result['transaction_datetime']);
echo $transactionDate->format('Y-m-d'); // "2023-12-05"
echo $transactionDate->format('H:i:s'); // "14:30:25"
echo $transactionDate->format('F j, Y \a\t g:i A'); // "December 5, 2023 at 2:30 PM"
?>
Timezone Note: transaction_datetime is a naive datetime (no timezone) representing the local time shown on the receipt. parsed_at includes timezone (UTC) for server timestamp.
Quick Start
Get up and running in 3 steps:
Create Account
Sign up for a free account to get started.
Get API Token
Generate your API token from your profile settings.
Process Receipt
Upload your first receipt using any of the code examples above.
Support
Need help? We're here to assist you:
- Email: [email protected]
- Documentation: Browse our guides and examples
- Community: Join our developer community
Ready to start? Create your account and process your first receipt today!