History and activity
Everything that happens on the account is journaled: who issued a document, when it went out by e-mail, whether KSeF accepted it, who marked the payment, which movements passed through the warehouse, when an employee logged in. Through the API you read those journals in four ways, depending on the question.
| Question | Endpoint | Scope | Pagination |
|---|---|---|---|
| What happened to this document? | GET /documents/{id}/history |
documents:read |
pages |
| What happened on the account today? | GET /activity |
activity:read |
cursor |
| What did this employee do? | GET /employees/{id}/activity |
employees:browse |
cursor |
| Which movements went through the warehouse? | GET /warehouse/movements |
warehouse:stock:read |
pages |
The journals are read-only and cover actions from every source: the API, the web and mobile apps, automations (recurring documents, the KSeF queue). The history of recurring rules is described in Recurring documents, webhook delivery history in Webhooks.
Document history
curl -s "https://sandbox.api.fakturnia.pl/external/v1/documents/681a3b2c4d5e6f7a8b9c0d1e/history?itemsPerPage=20" \
-H "Authorization: Bearer $TOKEN"
{
"success": true,
"data": {
"documentId": "681a3b2c4d5e6f7a8b9c0d1e",
"documentNumber": "FV/12/09/2026",
"entries": [
{ "id": "681a…2a", "type": "PAYMENT_RECEIVED", "createdAt": "2026-09-26T12:00:00.000Z", "actor": "employee", "employeeId": "681a…3b", "employeeName": "Ewa Kowalska", "origin": "app", "channel": null, "channelLabel": null, "changes": null, "data": { "origin": "app", "receivedPayment": "RECEIVED" } },
{ "id": "681a…29", "type": "KSEF_SENT", "createdAt": "2026-09-26T11:05:00.000Z", "actor": "owner", "employeeId": null, "employeeName": null, "origin": null, "channel": null, "channelLabel": null, "changes": null, "data": { "ksefNumber": "5271012345-20260926-AABBCC-DD", "sendMode": "instant" } },
{ "id": "681a…28", "type": "UPDATE", "createdAt": "2026-09-26T10:40:00.000Z", "actor": "owner", "employeeId": null, "employeeName": null, "origin": null, "channel": null, "channelLabel": null, "changes": [{ "field": "comments", "oldValue": "", "newValue": "Order #10234" }], "data": null },
{ "id": "681a…27", "type": "CREATE", "createdAt": "2026-09-26T10:30:00.000Z", "actor": "owner", "employeeId": null, "employeeName": null, "origin": "external_api", "channel": null, "channelLabel": null, "changes": null, "data": { "origin": "external_api", "source": "local" } }
],
"currentPage": 1, "itemsPerPage": 20, "totalCount": 4, "totalPages": 1
}
}
Entry types: CREATE, UPDATE (with the field diff in changes), DELETE, SENT_BY_EMAIL (recipients in data), DOWNLOAD, DOWNLOAD_XML, DOWNLOAD_UPO, PRINT, KSEF_SENT, KSEF_ERROR, PAYMENT_RECEIVED, PAYMENT_REVERTED, ADVANCE_INVOICE_LINKED / UNLINKED, SETTLEMENT_INVOICE_LINKED / UNLINKED, DOWNLOAD_CLIENT (downloaded by the recipient from a link). actor says whether the owner or an employee acted, and origin (when the entry records it) where the action came from: external_api, app or import. channel is mcp when an AI assistant connected through the MCP server acted, and channelLabel then names its credential (e.g. Claude, ChatGPT or a key label); in other entries both fields are null.
The endpoint is paginated like the lists (Pagination): currentPage, itemsPerPage (up to 100), with totalCount and totalPages in the response.
Account activity
GET /activity merges the three journals of the whole account (the owner and every employee): document actions, employee logins and account changes, warehouse operations. Entries come newest first.
curl -s "https://sandbox.api.fakturnia.pl/external/v1/activity?scope=documents&from=2026-09-26T00:00:00Z&limit=50" \
-H "Authorization: Bearer $TOKEN"
{
"success": true,
"data": {
"items": [
{ "id": "681a…1e", "scope": "document", "type": "CREATE", "createdAt": "2026-09-26T10:30:00.000Z", "employeeId": null, "employeeName": null, "entityId": "681a…1f", "entityName": "FV/12/09/2026", "entityType": "DOCUMENT", "entityDeleted": false, "changes": null, "data": { "origin": "external_api", "source": "local" } },
{ "id": "681a…1d", "scope": "auth", "type": "LOGIN", "createdAt": "2026-09-26T07:58:00.000Z", "employeeId": "681a…3b", "employeeName": "Ewa Kowalska", "entityId": null, "entityName": null, "entityType": null, "entityDeleted": false, "changes": null, "data": { "ip": "203.0.113.5", "device": "web" } }
],
"hasMore": true,
"nextBefore": "2026-09-26T07:58:00.000Z"
}
}
Filters:
| Parameter | Meaning |
|---|---|
scope |
all (default), documents, auth (logins), management (employee account changes), warehouse |
employeeId |
only one employee (id) or main (only the owner account) |
from, to |
time window (ISO 8601) |
q |
text: employee name or document number |
limit |
entries per page, default 30, max 100 |
before |
cursor: nextBefore from the previous page |
In the response, scope document covers document actions (with entityDeleted: true when the document was deleted later), warehouse covers warehouse operations (warehouse created, stock adjustment, warehouse documents), auth and management concern employee accounts.
Employee activity
GET /employees/{id}/activity returns the same shape as GET /activity, limited to one employee account, plus an employee object (as in GET /employees/{id}). It accepts scope, before and limit. An employee of another account answers 404.
Stock movements
GET /warehouse/movements is the ledger the stock levels are computed from: every receipt and issue with its document, quantity, unit cost and the person who recorded it. Filters: productId, warehouseId, documentId, type (comma-separated list: PZ, WZ, PW, RW, MM_OUT, MM_IN, INW, WYCENA), dateFrom / dateTo (YYYY-MM-DD). Paginated like the lists (itemsPerPage up to 100, default 50).
curl -s "https://sandbox.api.fakturnia.pl/external/v1/warehouse/movements?productId=681a3b2c4d5e6f7a8b9c0d2a&dateFrom=2026-09-01" \
-H "Authorization: Bearer $TOKEN"
{
"success": true,
"data": {
"movements": [
{ "id": "681a…4c", "productId": "681a…2a", "warehouseId": "681a…3b", "quantity": -2, "unitCost": null, "type": "WZ", "documentId": "681a…4d", "documentNumber": "WZ/3/09/2026", "date": "2026-09-26", "note": null, "employeeId": null, "employeeName": null, "createdAt": "2026-09-26T10:30:00.000Z" },
{ "id": "681a…4b", "productId": "681a…2a", "warehouseId": "681a…3b", "quantity": 25, "unitCost": 12.5, "type": "INW", "documentId": null, "documentNumber": null, "date": "2026-09-01", "note": "Opening balance", "employeeId": null, "employeeName": null, "createdAt": "2026-09-01T08:00:00.000Z" }
],
"currentPage": 1, "itemsPerPage": 50, "totalCount": 2, "totalPages": 1
}
}
The level of a product on a day is the sum of movements up to that day; GET /warehouse/stock?productId=…&asOf=… gives the same answer without walking the ledger. Module details: Warehouse.
Two styles of pagination
Resource lists and the document history are paginated by page number (currentPage, itemsPerPage, totalCount, totalPages): you know how much there is and can jump to any page. Activity streams (GET /activity, GET /employees/{id}/activity) merge several journals, so they use a time cursor: take nextBefore from a response and pass it as before until hasMore is false. New entries that arrive in the meantime do not shift the following pages. before is strict, though (it returns entries older than the given time), so entries with exactly the same timestamp, to the millisecond, as the last entry of a page can be skipped on the next page.