Quick Start Guide
This guide walks you through the most common integration scenario: pulling extraction results into your ERP or Materialwirtschaft system.
Prerequisites
- An API token (starting with
okt_live_)
- Your Auftragsnummer(n) that you want to look up
Step 1: Verify Your Token
Test that your token works by calling the health endpoint (no auth required) and then a simple list:
# Health check (no token needed)
curl https://api.oktavius.ai/v1/openapi/health
# List your completed extractions
curl -X GET "https://api.oktavius.ai/v1/openapi/extractions" \
-H "Authorization: Bearer okt_live_your_token_here"
const TOKEN = "okt_live_your_token_here";
const BASE = "https://api.oktavius.ai/v1/openapi";
const res = await fetch(`${BASE}/extractions`, {
headers: { Authorization: `Bearer ${TOKEN}` },
});
if (res.status === 401) {
console.error("Invalid token — check your API key");
} else {
const body = await res.json();
console.log(`${body.pagination.total} extractions available`);
}
import requests
TOKEN = "okt_live_your_token_here"
BASE = "https://api.oktavius.ai/v1/openapi"
res = requests.get(f"{BASE}/extractions",
headers={"Authorization": f"Bearer {TOKEN}"})
if res.status_code == 401:
print("Invalid token")
else:
body = res.json()
print(f"{body['pagination']['total']} extractions available")
Step 2: Query by Auftragsnummer
Find all extractions for a specific order. If multiple Regiescheine were uploaded for the same Auftrag, all of them are returned.
curl -X GET "https://api.oktavius.ai/v1/openapi/extractions?auftragsnummer=22201161" \
-H "Authorization: Bearer okt_live_your_token_here"
const res = await fetch(
`${BASE}/extractions?auftragsnummer=22201161`,
{ headers: { Authorization: `Bearer ${TOKEN}` } }
);
const { success, data, pagination } = await res.json();
for (const extraction of data) {
console.log(
`${extraction.auftragsnummer} — ${extraction.positionen_count} positions — ${extraction.status}`
);
}
res = requests.get(
f"{BASE}/extractions",
params={"auftragsnummer": "22201161"},
headers={"Authorization": f"Bearer {TOKEN}"},
)
body = res.json()
for ext in body["data"]:
print(f"{ext['auftragsnummer']} — {ext['positionen_count']} positions")
Example response:
{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"auftragsnummer": "22201161",
"baustelle": "Mokka",
"completed_at": "2026-03-03T14:00:00Z",
"created_at": "2026-03-03T13:00:00Z",
"positionen_count": 4
}
],
"pagination": { "page": 1, "page_size": 20, "total": 1 }
}
Once you have an extraction ID, fetch the full detail with all line items — this is the data you import back into your system.
curl -X GET "https://api.oktavius.ai/v1/openapi/extractions/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer okt_live_your_token_here"
const extractionId = data[0].id;
const detailRes = await fetch(`${BASE}/extractions/${extractionId}`, {
headers: { Authorization: `Bearer ${TOKEN}` },
});
const detail = await detailRes.json();
// Import positions into your system
for (const pos of detail.data.positionen) {
console.log(`${pos.menge} ${pos.eh} — ${pos.bezeichnung} (Art. ${pos.artikelnummer})`);
}
extraction_id = body["data"][0]["id"]
detail_res = requests.get(
f"{BASE}/extractions/{extraction_id}",
headers={"Authorization": f"Bearer {TOKEN}"},
)
detail = detail_res.json()["data"]
print(f"Auftrag: {detail['auftragsnummer']}")
print(f"Tätigkeit: {detail['regietaetigkeit']}")
for pos in detail["positionen"]:
print(f" {pos['menge']} {pos['eh']} — {pos['bezeichnung']} (Art. {pos['artikelnummer']})")
if detail["gesamtuebersicht"]:
print(f"Gesamt: {detail['gesamtuebersicht']['summe_gesamt']}")
Example detail response:
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "completed",
"completed_at": "2026-03-03T14:00:00Z",
"created_at": "2026-03-03T13:00:00Z",
"auftragsnummer": "22201161",
"baustelle": "Mokka",
"regietaetigkeit": "Aufgrund von mehrmaligen Planänderungen. Kabel eingezogen.",
"positionen": [
{
"kategorie": "ARBEIT",
"artikelnummer": "",
"bezeichnung": "Obermonteurstunden",
"menge": 55,
"eh": "Std",
"preis_einheit": 80.5,
"positionspreis": 4427.5
},
{
"kategorie": "MATERIAL",
"artikelnummer": "12011900716",
"bezeichnung": "NYM-J 5x2,5mm²",
"menge": 500,
"eh": "m",
"preis_einheit": 1.15,
"positionspreis": 575
}
],
"gesamtuebersicht": {
"summe_arbeit": 4427.5,
"summe_material": 836.75,
"summe_gesamt": 5264.24
}
}
}
Field Mapping for Your System
Based on the “Rückimport” requirements:
| Your Field | API Field | Notes |
|---|
| Auftragsnummer (required) | data.auftragsnummer | Project/order number |
| Text der durchgeführten Arbeiten | data.regietaetigkeit | May be null if not entered |
| Position: Menge (required) | positionen[].menge | Quantity |
| Position: Artikelnummer (required) | positionen[].artikelnummer | May be empty if no article match |
When artikelnummer is an empty string, the technician entered free text that could not be matched to an article in the catalog. Your system should handle this case (e.g. flag for manual resolution).
Step 4: Poll for New Results
To continuously sync new extractions, use the since parameter with the timestamp of your last successful sync:
curl -X GET "https://api.oktavius.ai/v1/openapi/extractions?since=2026-03-03T00:00:00Z" \
-H "Authorization: Bearer okt_live_your_token_here"
let lastSync = new Date("2026-03-03T00:00:00Z");
async function syncNewExtractions() {
const res = await fetch(
`${BASE}/extractions?since=${lastSync.toISOString()}`,
{ headers: { Authorization: `Bearer ${TOKEN}` } }
);
const { data } = await res.json();
for (const extraction of data) {
const detail = await fetchDetail(extraction.id);
importToYourSystem(detail);
}
if (data.length > 0) {
lastSync = new Date();
}
}
// Run every 5 minutes
setInterval(syncNewExtractions, 5 * 60 * 1000);
Error Handling
All error responses follow the same format:
{
"success": false,
"error": "Unauthorized",
"message": "Invalid API token."
}
| Status | Meaning |
|---|
401 | Invalid, expired, or missing API token |
403 | Token not associated with an organization |
404 | Extraction not found (or belongs to a different organization) |
429 | Rate limit exceeded (1,000 requests/hour) |
500 | Internal server error |