Разбор входящих счетов по API: загружаете счёт — получаете поля и файл для бухгалтерии. Балансовая модель, без подписки.Разбор входящих счетов через REST: загрузите документ, получите структурированные поля и выгрузку, готовую для бухгалтерии. Предоплаченный баланс, без подписки.
Принимает чужой входящий счёт (от поставщика) и возвращает структурированные данные плюс файл для бухгалтерии. Мы не выставляем счета и не принимаем платежи по счетам ваших клиентов — только разбор.Принимает входящий счёт поставщика и возвращает структурированные поля плюс файл, готовый для бухгалтерии. Мы не выставляем счета и не принимаем платежи по счетам ваших клиентов — только разбор.
Электронные счета читаем кодом — точно и без тарификации. Платите только за сканы и фото.Электронные счета разбираются кодом — точно и бесплатно. Вы платите только за сканы и фотографии.
X-Api-Key.Передавайте ключ в заголовке X-Api-Key.X-Api-Key: your_api_key_here
| МетодМетод | Path | Что делаетНазначение |
|---|---|---|
| POST | /v1/parse | Загрузить счёт (multipart: file, country)Загрузить счёт (multipart: file, country) |
| GET | /v1/parse/{job_id} | Результат разбора и поляСтатус задачи и разобранные поля |
| GET | /v1/usage | Расход и остаток балансаРасход и оставшийся баланс |
| GET | /v1/price | Цена (публично, без ключа)Цена (публично, без ключа) |
| GET | /v1/countries | Страны и форматы (публично)Страны и форматы (публично) |
Интерактивная документация: /docs · /redoc · openapi.jsonИнтерактивная документация: /docs · /redoc · openapi.json
curl -X POST https://duebuddy.work/v1/parse \
-H "X-Api-Key: your_api_key_here" \
-F "country=de" \
-F "[email protected]"
# {"ok":true,"job_id":41,"status":"queued","charged":true}
curl https://duebuddy.work/v1/parse/41 \
-H "X-Api-Key: your_api_key_here"
import requests, time
BASE = "https://duebuddy.work/v1"
HEAD = {"X-Api-Key": "your_api_key_here"}
def parse(path, country="de"):
with open(path, "rb") as f:
r = requests.post(f"{BASE}/parse", headers=HEAD,
files={"file": f}, data={"country": country}, timeout=60)
r.raise_for_status()
job = r.json()
for _ in range(30): # ждём результат
time.sleep(2)
out = requests.get(f"{BASE}/parse/{job['job_id']}", headers=HEAD, timeout=30).json()
if out.get("status") in ("done", "failed"):
return out
raise TimeoutError("parse timeout")
res = parse("invoice.pdf", "de")
print(res["fields"]) # поля счёта
const fd = new FormData();
fd.append("country", "us");
fd.append("file", fileInput.files[0]);
const r = await fetch("https://duebuddy.work/v1/parse", {
method: "POST",
headers: { "X-Api-Key": API_KEY },
body: fd
});
const { job_id } = await r.json();
const out = await fetch(`https://duebuddy.work/v1/parse/${job_id}`,
{ headers: { "X-Api-Key": API_KEY } }).then(r => r.json());
console.log(out.fields);
Сохраните как parse.html и откройте в браузере — перетащите файл, получите результат. Ключ хранится только в вашем браузере.Сохраните как parse.html, откройте в браузере и перетащите файл. Ключ хранится только в вашем браузере.
<!doctype html>
<meta charset="utf-8">
<title>DueBuddy parse</title>
<style>body{font:15px system-ui;margin:40px;max-width:640px}
#d{border:2px dashed #999;border-radius:12px;padding:40px;text-align:center}
pre{background:#f4f4f5;padding:14px;border-radius:8px;overflow:auto}</style>
<input id="k" placeholder="API key" style="width:100%;padding:8px">
<div id="d">Drop an invoice here (PDF / JPG / PNG / XML)</div>
<pre id="o">—</pre>
<script>
const d = document.getElementById("d"), o = document.getElementById("o");
d.ondragover = e => e.preventDefault();
d.ondrop = async e => {
e.preventDefault();
const f = e.dataTransfer.files[0];
const fd = new FormData();
fd.append("country", "de");
fd.append("file", f);
const head = { "X-Api-Key": document.getElementById("k").value };
const j = await fetch("https://duebuddy.work/v1/parse",
{ method: "POST", headers: head, body: fd }).then(r => r.json());
o.textContent = JSON.stringify(j, null, 2);
for (let i = 0; i < 30; i++) {
await new Promise(r => setTimeout(r, 2000));
const out = await fetch("https://duebuddy.work/v1/parse/" + j.job_id,
{ headers: head }).then(r => r.json());
o.textContent = JSON.stringify(out, null, 2);
if (out.status === "done" || out.status === "failed") break;
}
};
</script>
{
"ok": true,
"job_id": 41,
"status": "done",
"fields": {
"invoice_number": "RE-2026-04871",
"invoice_date": "2026-09-14",
"due_date": "2026-10-14",
"vendor_name": "Hartmann GmbH",
"net_amount": "1048.74",
"vat_amount": "199.26",
"gross_amount": "1248.00",
"currency": "EUR"
},
"fields_detailed": [{"key": "gross_amount", "value": "1248.00", "edited": false}]
}
Набор полей зависит от страны (country). Дополнительно доступна выгрузка в формат страны: XRechnung, ZUGFeRD, DATEV, 1С, UBL, FatturaPA и др.Набор полей зависит от country. Также доступны выгрузки в форматы конкретных стран: XRechnung, ZUGFeRD, DATEV, 1С, UBL, FatturaPA и другие.
| КодКод | detail | ПричинаПричина |
|---|---|---|
| 400 | unsupported_country | Страна не поддерживаетсяСтрана не поддерживается |
| 400 | unsupported_file_type | Не PDF/JPG/PNG/XMLНе PDF/JPG/PNG/XML |
| 400 | empty_file | Пустой файлПустой файл |
| 413 | file_too_large | Файл больше лимитаФайл превышает лимит |
| 429 | rate_limited | Больше 120 запросов в минутуБолее 120 запросов в минуту |
Мы обрабатываем входящие счета. Мы не выставляем счета от вашего имени и не принимаем платежи за вас.Мы обрабатываем входящие счета. Мы не выставляем счета от вашего имени и не принимаем платежи за вас.