AI-powered document processing. Upload invoices/POs, get structured data back.
Base URL: https://api.kynthar.com
All requests need your API key in the header:
X-API-Key: your_api_key_here
Get your API key: Login → Settings → Copy API Key
1. Upload file
POST /ingest/initiate
Content-Type: multipart/form-data
file: <your-pdf-file>
Response:
{
"key": "uploads/abc123/invoice.pdf",
"original_filename": "invoice.pdf"
}
2. Start processing
POST /ingest/finalize
Content-Type: application/json
{
"key": "uploads/abc123/invoice.pdf",
"original_filename": "invoice.pdf"
}
Response:
{
"doc_id": "01HX...",
"existed": false
}
GET /api/documents/{doc_id}
Response:
{
"doc_id": "01HX...",
"file_name": "invoice.pdf",
"doc_type": "invoice",
"processing_status": "COMPLETED",
"extracted_data": {
"invoice_number": "INV-2025-001",
"total_amount": 1250.00,
"currency_code": "USD",
"vendor_name": "Acme Corp",
"invoice_date": "2025-01-15"
}
}
Status values:
QUEUED - Waiting to processPROCESSING - Processing nowCOMPLETED - Done! Data readyFAILED - Something went wrongGET /api/documents?limit=20&status=COMPLETED
Response:
{
"documents": [...],
"total": 156,
"limit": 20,
"offset": 0
}
Get notified instantly when documents finish processing.
https://your-server.com/webhooks/kyntharPOST https://your-server.com/webhooks/kynthar
X-Webhook-Event: invoice.parsed
X-Webhook-Signature: sha256=abc...
{
"event": "invoice.parsed",
"timestamp": "2025-01-15T10:30:00Z",
"data": {
"doc_id": "01HX...",
"doc_type": "invoice",
"processing_status": "COMPLETED"
}
}
Just return 200 OK within 5 seconds. Do heavy work async.
app.post('/webhooks/kynthar', (req, res) => {
res.status(200).send('OK'); // Respond immediately
// Process async
handleWebhook(req.body).catch(console.error);
});
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Email documents to your ingest address: {your-company-id}@ingest.kynthar.com
Get your address from Settings.
When you hit a limit, you'll get 429 Too Many Requests.
All errors return JSON:
{
"error": "Invalid API key"
}
Common errors:
401 - Bad/missing API key404 - Document not found429 - Rate limit or document limit hit500 - Our bad, we're on itconst fetch = require('node-fetch');
const FormData = require('form-data');
const fs = require('fs');
const API_KEY = 'your_api_key';
const API = 'https://api.kynthar.com';
async function processDocument(filePath) {
// 1. Upload
const form = new FormData();
form.append('file', fs.createReadStream(filePath));
const init = await fetch(
`${API}/ingest/initiate`,
{
method: 'POST',
headers: { 'X-API-Key': API_KEY },
body: form
}
).then(r => r.json());
// 2. Finalize
const result = await fetch(
`${API}/ingest/finalize`,
{
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
key: init.key,
original_filename: init.original_filename
})
}
).then(r => r.json());
console.log('Document ID:', result.doc_id);
// 3. Poll for completion (or use webhooks!)
while (true) {
const doc = await fetch(
`${API}/api/documents/${result.doc_id}`,
{ headers: { 'X-API-Key': API_KEY } }
).then(r => r.json());
if (doc.processing_status === 'COMPLETED') {
console.log('Done!', doc.extracted_data);
return doc;
}
await new Promise(r => setTimeout(r, 5000));
}
}
processDocument('./invoice.pdf');
import requests
import time
API_KEY = 'your_api_key'
API = 'https://api.kynthar.com'
headers = {'X-API-Key': API_KEY}
def process_document(file_path):
# 1. Upload
with open(file_path, 'rb') as f:
init = requests.post(
f'{API}/ingest/initiate',
headers=headers,
files={'file': f}
).json()
# 2. Finalize
result = requests.post(
f'{API}/ingest/finalize',
headers={
**headers,
'Content-Type': 'application/json'
},
json={
'key': init['key'],
'original_filename':
init['original_filename']
}
).json()
doc_id = result['doc_id']
print(f'Document ID: {doc_id}')
# 3. Poll for completion
while True:
doc = requests.get(
f'{API}/api/documents/{doc_id}',
headers=headers
).json()
if doc['processing_status'] == 'COMPLETED':
print('Done!', doc['extracted_data'])
return doc
time.sleep(5)
process_document('invoice.pdf')
# 1. Upload
INIT=$(curl -X POST \
https://api.kynthar.com/ingest/initiate \
-H "X-API-Key: your_api_key" \
-F "file=@invoice.pdf")
KEY=$(echo $INIT | jq -r '.key')
FILENAME=$(echo $INIT | jq -r '.original_filename')
# 2. Finalize
RESULT=$(curl -X POST \
https://api.kynthar.com/ingest/finalize \
-H "X-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d "{\"key\":\"$KEY\",\"original_filename\":\"$FILENAME\"}")
DOC_ID=$(echo $RESULT | jq -r '.doc_id')
echo "Document ID: $DOC_ID"
# 3. Get result
curl https://api.kynthar.com/api/documents/$DOC_ID \
-H "X-API-Key: your_api_key"
Email: support@kynthar.com