Partner APIversion 1.3.0 · net prices, stock, orders and invoices
Quick start
first request in 3 stepsThe API returns your account's net prices and DACO stock levels. Prices are the same as when you sign in to the B2B platform. One request handles up to 500 product codes. You can also place orders through the API — they reach DACO like orders from the platform — and fetch your invoices and corrections.
- Base URL
https://api.daco-germany.de/v1- Version
1.3.0— in the URL as/v1- Format
- JSON, UTF-8, over HTTPS
- Key
- issued by your DACO account manager — how to get a key
First request
- Ask for a test key. It starts with
dk_test_and returns the real prices and stock of your account. - Check the key.
GET /meshows the account, the currency and the key mode.bashcurl https://api.daco-germany.de/v1/me \ -H "Authorization: Bearer dk_test_XXXXXXXX"
Windowscurl.exe https://api.daco-germany.de/v1/me -H "Authorization: Bearer dk_test_XXXXXXXX"
- Get prices and stock.
POST /pricestakes a list of product codes.bashcurl -X POST https://api.daco-germany.de/v1/prices \ -H "Authorization: Bearer dk_test_XXXXXXXX" \ -H "Content-Type: application/json" \ -d '{"items":["329986","BA0210","XX1"]}'A bash command (Linux, macOS, Git Bash, WSL).WindowsSave the request body to a file namedbody.json, encoded as UTF-8:{"items":["329986","BA0210","XX1"]}Send the file. Usecurl.exe— in PowerShell, plaincurlis a different command.curl.exe -X POST https://api.daco-germany.de/v1/prices -H "Authorization: Bearer dk_test_XXXXXXXX" -H "Content-Type: application/json" -d "@body.json"
API keys
Authorization header · test modeRequests to /me, /prices, /orders and /invoices require a key in the Authorization header. GET /status works without a key.
- A key is 40 characters long:
dk_test_ordk_live_followed by 32 letters or digits. - One key belongs to one customer account. Prices, currency and profile are the same as when you sign in to B2B.
- An account can have several keys. The rate limit is counted separately for each key.
- There is no other way to authenticate.
Basic, a key without the wordBearerand a key in the URL all return401.
Test and live keys
test mode| Feature | Test | Live |
|---|---|---|
| Key starts with | dk_test_ | dk_live_ |
| Prices and stock | real, from your account | the same |
Orders POST /orders | checked only: 200, status: validated, no number | placed at DACO: 201, number API-… |
| Response header | x-daco-sandbox: 1 | none |
account.sandbox field in /me | true | false |
| Rate limit | 60 requests per minute | 60 requests per minute |
| Console on this page | yes | no |
- A test key lets you check the connection and the data format against the real data of your account.
- The
x-daco-sandbox: 1header is sent with status codes 200, 400 and 503. It is not sent with 401 or 429. - A test key checks an order exactly like a live key — prices, stock, account status and credit limit — but does not place it. Nothing reaches DACO.
- There is no test data, no dummy products and no way to force errors.
- The URL is the same. So is the rate limit: 60 requests per minute, counted separately for each key.
- Calls are recorded in the DACO log like any other call.
How to get a key
- Keys are issued by DACO. You cannot create a key yourself on the B2B platform.
- Contact your account manager (contact). Include your customer code and a short description of the integration.
- The full key is shown only once, when it is created. Store it right away.
- A lost key cannot be recovered. DACO stores only its hash and the first 12 characters. We will issue a new one.
- Keys are revoked by DACO. Revocation takes effect with the next request, which returns
401.
Keeping your key safe
- Keep the key on your server. The API is meant for server-to-server calls and sends no CORS headers, so a page on another domain cannot call it.
- Never paste the key into emails or support requests. The first 12 characters are enough.
- After a series of failed attempts from one IP address, that address gets
429until the end of the minute, even with a valid key.
Try it
a real API requestSend a request from this page and see the response. The request is real. /me, /prices and /invoices need a test key. Those requests count toward the rate limit of 60 per minute and are recorded in the DACO log.
Response
The same request as curl
curl https://api.daco-germany.de/v1/status
curl.exe https://api.daco-germany.de/v1/status
Endpoints
read and order| Method | Path | Key | Description | Response codes |
|---|---|---|---|---|
| GET | /status | no key | Service status and data age | 200, 503 |
| GET | /me | key | Key check: account, currency, mode | 200, 401, 403, 429, 500 |
| POST | /prices | key | Net prices and stock for a list of codes | 200, 400, 401, 403, 429, 500, 503 |
| POST | /orders | key | Place an order | 200, 201, 400, 401, 403, 409, 429, 500, 503 |
| GET | /orders | key | List your orders | 200, 400, 401, 403, 429, 500 |
| GET | /orders/{orderNo} | key | Order status and lines | 200, 401, 403, 404, 429, 500 |
| GET | /invoices | key | Invoices and corrections: a filtered list | 200, 400, 401, 403, 429, 500, 503 |
| GET | /invoices/{id} | key | One document with its lines | 200, 401, 403, 404, 429, 500, 503 |
- Append the path to the base URL. Paths are case-sensitive:
/STATUSreturns404. - Do not add a trailing slash:
/me/returns308. Some HTTP clients do not resend aPOSTafter a redirect. - Checks run in this order: IP address block (
429), key (401), key rate limit (429), account (403) and finally the request itself. The first error is returned. - All endpoints except
POST /ordersare read-only. Such a request can be repeated safely. Each repeat counts toward the rate limit. POST /ordersplaces an order. Retry it only with the sameIdempotency-Key— then no second order is created.
GET https://api.daco-germany.de/v1/status
GET https://api.daco-germany.de/v1/me
POST https://api.daco-germany.de/v1/prices
POST https://api.daco-germany.de/v1/orders
GET https://api.daco-germany.de/v1/orders
GET https://api.daco-germany.de/v1/orders/{orderNo}
GET https://api.daco-germany.de/v1/invoices
GET https://api.daco-germany.de/v1/invoices/{id}content-type: application/json cache-control: no-store x-daco-api-version: 1.3.0 x-daco-sandbox: 1
x-daco-sandbox is sent only for a test key.GET/status
no keyService status and data age. It tells you whether POST /prices will return prices and stock right now. It requires no key and does not count toward the rate limit.
Request body: none.
200 — status ok. 503 — status degraded. Note: here 503 returns the same status object, not an error object.
Response fields
200 and 503| Field | Type | Description |
|---|---|---|
status | string | ok — /prices will return prices and stock. degraded — the data is older than 5 minutes or its age is unknown. |
apiVersion | string | API version, currently 1.3.0. |
dataAgeSec | integer | null | Age of the oldest data set, in seconds. null — the age is unknown. |
GET/me
key requiredChecks the key. Returns the account, the currency, the key mode and the data age.
Request body: none. The Authorization header is all you need.
/me responds with 200 even when the data is out of date. Check the data age in dataAgeSec or with /status.
Response fields
200| Field | Type | Description |
|---|---|---|
apiVersion | string | API version. |
account.customerCode | string | Your customer code at DACO. |
account.name | string | Company name from the customer record. |
account.currency | string | Account currency: PLN or EUR. |
account.sandbox | boolean | true for a test key. |
account.profile | string | Customer type set by DACO: hurt — wholesaler, sklep — retail shop. These are fixed identifiers. |
key.prefix | string | The first 12 characters of the key. |
key.label | string | null | Key description assigned by DACO. |
key.createdAt | string | When the key was created: ISO 8601 in UTC, for example 2026-10-08T17:47:05Z. |
dataAgeSec | integer | null | Data age, as in /status. |
POST/prices
key requiredYour account's net price and the stock level for a list of product codes. A code that cannot be priced does not fail the request. The response is still 200, and the item carries an error field.
An invalid request can get 503 as well. Data freshness is checked before the request body.
Request body
JSON| Field | Type | Description |
|---|---|---|
items | array of string · required | DACO product codes (the “DACO ID” from the catalog). From 1 to 500 different codes. |
- A code is 1 to 40 characters long. Leading and trailing whitespace is ignored. Letter case does not matter:
ba0210isBA0210. - Repeated codes are merged and the first occurrence is kept. The limit of 500 is counted after merging. The response then has fewer items than the request.
- Codes are matched exactly. There is no lookup by EAN, OE number or name.
- Body: JSON in UTF-8, up to 256 KB. The
Content-Type: application/jsonheader is recommended. Other fields in the body are ignored.
Response fields
200| Field | Type | Description |
|---|---|---|
currency | string | Currency of every price in the response: PLN or EUR. This is the account currency. |
dataAgeSec | integer | Age, in seconds, of the oldest data set used for the response (prices, discounts, stock). Never more than 300. |
items | array | One item per code, in request order. |
items[].code | string | The code as sent, without leading or trailing whitespace. |
items[].name | string | Product name, always in Polish. Absent for NOT_FOUND. |
items[].netPrice | number | Net unit price, to 2 decimal places. Absent when error is set. |
items[].stock | integer | Quantity available in the DACO warehouse. 0 — out of stock. Absent for NOT_FOUND. |
items[].carton | object · optional | Present only when a carton price applies to your account and this product. qty — pieces in a full carton. netPrice — net unit price for pieces ordered in full cartons. |
items[].error | string · optional | NOT_FOUND — unknown code, or a product of a brand not available on your account; the item has only code and error. NO_PRICE — the product exists, but your account has no net price for it; name and stock are still returned. Field absent — the item is priced. |
Good to know
- Prices are net, per piece. The API returns neither the VAT rate nor a gross price.
- A price is a JSON number:
20.10arrives as20.1, and335.00as335. - Stock is counted for the main warehouse only. Other warehouses are not included.
- Match the response to the request by
code, trimmed and case-insensitive. Not by position: once repeated codes are merged, positions shift. - The API does not provide a list of codes. Take the codes from the DACO catalog or price list.
- The API does not return EANs, OE numbers, English names, minimum quantities or delivery dates.
- There is no pagination. One request takes at most 500 codes.
POST/orders
key requiredPOST /orders places an order on your account. Prices and stock are worked out exactly as in /prices — we do not take prices from the request. The order reaches DACO the same way as an order from the B2B platform; check its status with GET /orders/{orderNo}.
201 — order accepted. 200 — test key: the order was only checked. With partial: true, lines rejected for stock, price or code do not fail the order.
Request body
JSON| Field | Type | Description |
|---|---|---|
items | array · required | Lines: from 1 to 500 different codes. A repeated code is a DUPLICATE_ITEM error. |
items[].code | string · required | DACO product code, as in /prices. Up to 40 characters, case-insensitive. |
items[].qty | integer · required | Quantity in pieces: a whole number from 1 to 100 000. |
partial | boolean · optional | true (default) — we accept what we can and reject the rest with a reason. false — all or nothing: any rejected line returns 409. |
reference | string · optional | Your own order number, up to 50 characters. It is returned in responses and stored with the order at DACO. |
note | string · optional | A note for the order, up to 500 characters. |
Idempotency key (Idempotency-Key)
- The
Idempotency-Keyheader is required: 8 to 100 characters, ideally a UUID. A new order needs a new key. - The same key with the same body returns the same order:
201and anidempotent-replayed: trueheader. No second order is created. - The same key with a different body:
409CONFLICT,details.reason:IDEMPOTENCY_KEY_REUSED. - The key applies to your account, also after the API key is replaced. Refusals (
400,403,409,503) are not remembered — once the cause is fixed, the same key places the order.
Response fields
201 · 200| Field | Type | Description |
|---|---|---|
orderNo | string | null | DACO order number, for example API-261028-8F2K. null for a test key. |
status | string | queued once accepted. Test key: validated. Later states are listed in the status table below. |
sandbox | boolean | true for a test key — the order was not placed. |
reference | string | null | Your order number from the request. |
currency | string | Price currency: PLN or EUR. |
totalNet | number | Net value of the accepted lines. |
createdAt | string | null | When the order was accepted: ISO 8601 in UTC. null for a test key. |
accepted | array | Accepted lines: code, qty, netPrice. Full cartons may be a separate line at the carton price, with carton: true. |
rejected | array | Rejected quantities: code, qty, reason, and for STOCK and NO_PRICE also available — the quantity in stock. |
Line rejection reasons
rejected[].reason| Reason | When |
|---|---|
NOT_FOUND | Unknown code, or a product of a brand not available on your account — as in /prices. |
NO_PRICE | Your account has no net price for this product. We never substitute the catalog price. |
STOCK | Out of stock or not enough. With partial: true we accept available pieces and reject the rest. |
Order of checks
- Body and
Idempotency-Key(400). A repeat of an earlier order returns it right away. - Data freshness (
503), then the price and stock of each line. - Account status and credit limit: the limit minus the balance, minus open orders, minus the gross value of this order (
403CREDIT_BLOCKED). Cash-on-delivery invoices never block. - Acceptance: stock is checked once more at the moment of saving. The pieces of accepted lines are reserved at once —
/pricesalready shows the lower stock.
VALIDATION reasons for orders
details.reason| Reason | When |
|---|---|
IDEMPOTENCY_KEY_REQUIRED | The Idempotency-Key header is missing in POST /orders. |
INVALID_IDEMPOTENCY_KEY | The key is shorter than 8 or longer than 100 characters, or has characters other than letters, digits and . _ : -. |
INVALID_ITEM | Line details.index: an invalid code, or qty is not a whole number from 1 to 100 000. |
DUPLICATE_ITEM | Line details.index repeats the code of an earlier line. |
INVALID_FIELD | Invalid field details.field: partial, reference or note. |
INVALID_PARAM | GET /orders: invalid parameter details.param — from or limit. |
Plus INVALID_JSON, BODY_TOO_LARGE, ITEMS_REQUIRED and TOO_MANY_ITEMS as in /prices — the line limit is 500.
GET/orders/{orderNo}
key requiredStatus and lines of one order: items — as sent to DACO, erp — the order at DACO once it exists. An order of another account returns 404, the same as a number that does not exist.
Order statuses
status| Status | Meaning |
|---|---|
queued | Accepted, waiting to be passed to the DACO system. |
sent_to_erp | Passed to the DACO system. The order at DACO is usually created within a few minutes. |
accepted | The order exists at DACO. erp shows its number, fulfilment state and lines — quantities can be lower than sent. |
rejected | The DACO system did not take the order. Contact DACO. |
cancelled | The order was cancelled at DACO. |
Good to know
- The status changes asynchronously. Check it again after a few minutes, at most once a minute per order.
- The order at DACO can have lower quantities than sent — compare
itemswitherp.items. - Values are net. DACO purchase costs are never returned.
GET/invoices
key requiredInvoices and corrections of your account: headers, amounts, the amount to settle, the KSeF number and orders. The same documents as under Finance on the B2B platform. No files: the original is in KSeF.
Request body: none. Filters go in URL parameters.
An invalid request can get 503 as well. Invoice data freshness is checked before the parameters.
URL parameters
all optional| Field | Type | Description |
|---|---|---|
from | string (date) · optional | First issue date, YYYY-MM-DD, inclusive. |
to | string (date) · optional | Last issue date, YYYY-MM-DD, inclusive. Defaults to today. |
open | boolean · optional | true — only documents with an amount to settle (outstanding other than 0). false — only settled ones. |
type | string · optional | Document types, comma-separated, for example FS,FSK. At most 10. |
correction | boolean · optional | true — corrections only. false — invoices only, without corrections. |
number | string · optional | The exact document number, for example D0C/26/10112/FS. Letter case does not matter. |
limit | integer · optional | Documents per page: 1 to 500. Defaults to 100. |
offset | integer · optional | How many documents to skip. nextOffset points to the next page. |
- Without
fromandto: the last 90 days. Withopen=trueornumber: the whole history available in the API. - Only
from: up to today. Onlyto: the 90 days that end onto. The range is at most 366 days. - Invoice history in the API: the last 2 years, plus older documents with an amount to settle.
- Other parameters are ignored.
?from=2026-10-01&to=2026-10-31 ?open=true ?type=FSK&from=2026-01-01 ?number=D0C/26/10112/FS ?limit=500&offset=500
Response fields
200| Field | Type | Description |
|---|---|---|
dataAgeSec | integer | Age, in seconds, of the oldest invoice data set. Never more than 3000. |
from | string | null | The first day applied. null — no limit. |
to | string | null | The last day applied. null — no limit. |
total | integer | Number of all documents that match. |
limit | integer | Page size. |
offset | integer | Documents skipped. |
nextOffset | integer | null | The offset of the next page. null — this is the last page. |
items | array | Documents from the oldest, by issue date. |
items[].id | string | Document identifier. Use it to fetch the details. |
items[].number | string | Document number, for example D0C/26/10112/FS. |
items[].type | string | Type: FS — invoice, FSK — correction, FE / FEK — export invoice and its correction. Other types are possible. |
items[].issueDate | string (date) | Issue date. |
items[].dueDate | string (date) | null | Payment due date. |
items[].currency | string | Document currency: PLN or EUR. |
items[].exchangeRate | number | null | Exchange rate from the document. null — the document has none. |
items[].net | number | Net amount in the document currency. Negative in a correction that reduces the amount. |
items[].vat | number | VAT amount. |
items[].gross | number | Gross amount. |
items[].outstanding | number | Amount to settle. 0 — settled. Negative — an unsettled credit from a correction. |
items[].paymentMethod | string | null | transfer, cash, card, cash_on_delivery or other. |
items[].ksefNumber | string | null | The document number in KSeF. null — the document has no KSeF number. |
items[].customer | object | Buyer: code — customer code, name — name. A head office also sees its branches here. |
items[].isCorrection | boolean | true — the document is a correction. |
items[].correctionReason | string | null | Corrections only: the reason for the correction from the document, for example Zwrot towaru (goods returned). The same text is in KSeF. It may be in Polish or English. |
items[].correctedInvoice | object | null | Corrections only: the document corrected directly (id, number). |
items[].originalInvoice | object | null | Corrections only: the first document in the chain of corrections (id, number). |
items[].orders | array | Orders on this document: orderNo — the order number on the platform, reference — your order reference, erpNumber — the order number in the ERP. A correction has an empty list. |
VALIDATION error reasons
details.reason| Reason | When | Extra field |
|---|---|---|
INVALID_PARAM | A parameter is malformed, for example a date that does not exist or a limit out of range. | param — the parameter name |
RANGE_INVALID | from is after to. | none |
RANGE_TOO_LONG | The range is longer than 366 days. | maxDays: 366 |
FROM_TOO_OLD | from is earlier than the invoice history in the API. | minFrom — the earliest allowed date |
Good to know
- Corrections are separate documents on the list. The
correction=truefilter shows corrections only, andcorrectedInvoicepoints to the corrected document. - A head office sees its own documents and those of its branches. A branch sees only its own.
- Amounts are in the document currency, to 2 decimal places. An amount is a JSON number:
20.10arrives as20.1. - The order is fixed: from the oldest. New documents are added at the end, so pages counted from the start do not shift.
- A new document appears in the API a few minutes after it is issued in the ERP.
- The API returns neither PDF nor XML. Download the document from KSeF using
ksefNumber.
GET/invoices/{id}
key requiredOne document with its lines. Take the id from the GET /invoices list. A document number contains slashes — look it up on the list with the number parameter.
Request body: none.
404 — there is no such document, or it belongs to another account. The response is the same in both cases.
Response fields
200The document fields are the same as in GET /invoices, plus dataAgeSec and items:
| Field | Type | Description |
|---|---|---|
items[].line | integer | Line number, from 1. |
items[].code | string | null | DACO product code. |
items[].name | string | null | Product name, in Polish. |
items[].qty | number | Quantity. In a correction: the change in quantity, usually negative. |
items[].unit | string | null | Unit from the document, for example SZT (piece) or KPL (set). |
items[].netPrice | number | Net unit price. |
items[].netValue | number | Net line value from the document. In a correction: the change in value. |
items[].vatRate | number | null | VAT rate in percent, for example 23. |
items[].correction | object | null | Corrections only: before and after — quantity, price and value before and after the correction. difference — the change in quantity, price and value. null in an invoice. |
Good to know
- A correction line:
qtyandnetValueare the change,netPriceis the price after the correction. The full picture is incorrection. - A price correction has a
qtyof 0 and the change in value innetValue. - The values before and after are quantity × price, to 2 decimal places. The change in value comes from the document.
correctionmay benullin a correction from before this data was available in the API. Only the change fields are present then.- A document older than 2 years may have no lines. In that case
itemsis empty. - The API returns no cost, margin or warehouse data for a document.
Errors
one format · 9 codesAn error always has the same shape: an error object with code, message and sometimes details. Identify errors by error.code — the codes are stable.
error.message is meant for people. It is in Polish when the Accept-Language header starts with pl, and in English otherwise. Codes and field names are the same in both languages.
Error codes
error.code| Code | HTTP | When | What to do |
|---|---|---|---|
VALIDATION | 400 | Invalid request. The reason is in details.reason. | Fix the request. Do not retry it unchanged. |
UNAUTHORIZED | 401 | Missing, invalid or revoked key. | Check the key and the header. Do not retry. |
FORBIDDEN | 403 | The key is valid, but the customer account is not available. | Contact DACO. |
CREDIT_BLOCKED | 403 | POST /orders: order dispatch is on hold — the account is blocked or invoices are overdue (details.reason: BLOCKED), or the order exceeds your credit limit (CREDIT_LIMIT). | Settle your invoices or reduce the order. Questions go to your DACO account manager. |
NOT_FOUND | 404 | GET /orders/{orderNo}: there is no such order on your account. GET /invoices/{id}: there is no such document, or it belongs to another account. | Check the order number, or the document id on the GET /invoices list. Do not retry it unchanged. |
CONFLICT | 409 | POST /orders: the same Idempotency-Key with a different body (IDEMPOTENCY_KEY_REUSED), rejected lines with partial: false (ITEMS_REJECTED), or nothing to accept (NO_ACCEPTED_ITEMS). | Fix the order. A new body needs a new Idempotency-Key. |
RATE_LIMIT | 429 | More than 60 requests per minute for one key: details.limitPerMinute. Or an IP address blocked after a series of invalid keys: no details. | Wait the number of seconds given in the Retry-After header. |
INTERNAL | 500 | Unexpected server error. | Retry later. If it keeps happening, contact DACO. |
UNAVAILABLE | 503 | /prices and POST /orders: the data is older than 5 minutes. /invoices: the invoice data is older than 50 minutes. Or the age is unknown. details.dataAgeSec is present when the age is known. For an order, also when the account status cannot be checked. | Retry in a few minutes. Check GET /status. There is no Retry-After header. |
503 is permanent when the account currency is neither PLN nor EUR. In that case, contact DACO.
VALIDATION error reasons
details.reason| Reason | When | Extra field |
|---|---|---|
INVALID_JSON | The body is empty or is not valid JSON. | none |
BODY_TOO_LARGE | The body is larger than 256 KB. | maxBytes: 262144 |
ITEMS_REQUIRED | items is missing, is not an array or is empty. | none |
TOO_MANY_ITEMS | More than 500 different codes. | max: 500 |
INVALID_ITEM | An element is not a string, is empty or is longer than 40 characters. The first one found is reported. | index — position in the array, counted from 0 |
Item errors and special cases
NOT_FOUNDandNO_PRICEinitems[].errorare not request errors. The response status is200.- Lines rejected by
POST /orders(rejected[].reason) are not request errors either. The response status is201. GET /statuswith503returns the status object, not an error object.- Wrong method, for example
GET /prices: status405and an empty body. - Unknown path: status
404and an HTML page instead of JSON.
Limits
counted per key| Limit | Value | When exceeded |
|---|---|---|
| Requests | 60 per minute per key | 429 RATE_LIMIT and a Retry-After header |
Codes in one /prices request | 500 unique codes | 400 TOO_MANY_ITEMS |
| Code length | 40 characters | 400 INVALID_ITEM |
| Request body | 256 KB (262,144 bytes) | 400 BODY_TOO_LARGE |
- The minute starts with the first request. All 60 requests can be used at once.
- Every request to
/me,/prices,/ordersand/invoiceswith a recognized key counts, including requests that end with 400, 403, 404, 409 or 503. - Not counted:
GET /statusand requests that end with401. Retry-Aftergives the number of seconds until the end of the minute, from 1 to 60. There are no headers reporting the remaining quota.- The full catalog, about 8,000 codes, takes 16–17 requests of 500 codes each. That fits within one minute.
- After a series of failed key attempts from one IP address, that address gets
429until the end of the minute, with aRetry-After: 60header.
Data freshness
5-minute thresholdThe API answers from a copy of the ERP data kept on the B2B server. It does not query the ERP on every request. When the data is older than 5 minutes, the API responds with 503 instead of returning outdated figures.
How often the data is refreshed
| Data | Refresh interval |
|---|---|
| Stock | about every 30 seconds |
| Prices and discounts | about every 60 seconds |
| Product names | every 5 minutes. A new product appears in the API up to 5 minutes after it is created. Until then its code returns NOT_FOUND. |
| Carton quantities | every 60 minutes |
| Invoices | every 5 minutes, invoice lines every 10 minutes |
dataAgeSecis the age, in seconds, of the oldest data set used for the response./prices,/statusand/mereport the same number. It is usually no more than about 65.- Above 300 seconds, or when the age is unknown:
/pricesresponds with503UNAVAILABLE, and/statuswith503and statusdegraded./mestill responds with200. /invoiceshas its own threshold: 50 minutes. ItsdataAgeSecis the age of the oldest invoice data set./statuscovers prices and stock only.- Data does not age just because nothing changed in the ERP. The age is counted from the last successful refresh.
- Short periods of
503are possible, for example at night around 02:10–03:40 Polish time. Retry after a moment.
Versions and OpenAPI
currently 1.3.0- The version is part of the URL (
/v1) and is also given as a three-part number (1.3.0). - You will find the number in the
x-daco-api-versionheader of/me,/pricesand/invoicesresponses, in theapiVersionfield (/me,/status) and in the OpenAPI file. - Ignore response fields you do not recognize.
OpenAPI specification OpenAPI 3.0.3
A machine-readable description of the API: https://api.daco-germany.de/v1/openapi.json.
Import the file into Postman, Insomnia or a code generator. The server URL is already in the file.
Changelog
| Date | Version | Changes |
|---|---|---|
| 2026-10-28 | 1.3.0 | New endpoints GET /invoices and GET /invoices/{id}: invoices and corrections with their lines, the KSeF number and related orders. Error code NOT_FOUND also for documents. |
| 2026-10-28 | 1.2.0 | Orders: POST /orders with the Idempotency-Key header, GET /orders and GET /orders/{orderNo}. Error codes CREDIT_BLOCKED, NOT_FOUND and CONFLICT. |
| 2026-10-08 | 1.1.0 | New endpoint POST /prices: net price and stock for up to 500 codes. Error codes VALIDATION and UNAVAILABLE. The dataAgeSec field now covers all data sets. Request body limit of 256 KB. |
| 2026-10-01 | 1.0.0 | Keys and the Authorization: Bearer header. Limit of 60 requests per minute. Error format. GET /status and GET /me. Documentation and the OpenAPI file. Test mode. |
Contact
keys and questionsYour DACO account manager issues keys and answers questions.
- api@daco-germany.de
- Phone
- +48 883 115 115
- Company
- Wojciech Rzepka DACO Group Sp. k., ul. Centralna 55, 31-586 Kraków, Poland
What to include in a support request
- the first 12 characters of the key (the
key.prefixfield from/me) — never the full key, - the date and time of the request,
- the method and path, the HTTP status and
error.code.
DACO keeps a log of API calls: key identifier, account, time, method, path, response status, duration, number of codes, IP address and error code. Request and response bodies are not logged. Entries are kept for 90 days.
